ASP.NET CORE 1.0,来自另一个程序集的 AppSettings

Dan*_*ani 3 c# appsettings asp.net-core asp.net-core-1.0

我有一个应用程序拆分为两个项目:一个 Web 应用程序和一个类库。仅Startup在网络应用程序中:

var builder = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
Run Code Online (Sandbox Code Playgroud)

我希望将 appsettings.json 放在该类库中并从那里加载。那可能吗?我怎样才能做到这一点?

ceb*_*bru 5

我发现的最佳解决方案需要创建新的 IFileProvider 和 IFileInfo,然后将 JSON 设置文件嵌入到程序集中。

该解决方案重用现有的 AddJsonFile 逻辑。这样你只需要告诉配置系统如何以及在哪里找到 JSON 文件,而不是如何解析它。

该解决方案与.NET Core 1.0兼容。

用法:

public class Startup
{
    private readonly AppSettings _appSettings;

    public Startup(IHostingEnvironment env)
    {
        Assembly assembly = GetType().GetTypeInfo().Assembly;

        new ConfigurationBuilder()
          .AddEmbeddedJsonFile(assembly, "appsettings.json")
          .AddEmbeddedJsonFile(assembly, $"appsettings.{env.EnvironmentName.ToLower()}.json")
          .Build();
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

通过更新类库的 project.json 来嵌入文件:

...
"buildOptions": {
  "embed": [
    "appsettings.json",
    "appsettings.development.json",
    "appsettings.production.json"
  ]
}
...
Run Code Online (Sandbox Code Playgroud)

IEmbeddedFileInfo 实现:

public class EmbeddedFileInfo : IFileInfo
{
    private readonly Stream _fileStream;

    public EmbeddedFileInfo(string name, Stream fileStream)
    {
        if (name == null) throw new ArgumentNullException(nameof(name));
        if (fileStream == null) throw new ArgumentNullException(nameof(fileStream));

        _fileStream = fileStream;

        Exists = true;
        IsDirectory = false;
        Length = fileStream.Length;
        Name = name;
        PhysicalPath = name;
        LastModified = DateTimeOffset.Now;
    }

    public Stream CreateReadStream()
    {
        return _fileStream;
    }

    public bool Exists { get; }
    public bool IsDirectory { get; }
    public long Length { get; }
    public string Name { get; }
    public string PhysicalPath { get; }
    public DateTimeOffset LastModified { get; }
}
Run Code Online (Sandbox Code Playgroud)

IFileInfo 实现:

public class EmbeddedFileProvider : IFileProvider
{
    private readonly Assembly _assembly;

    public EmbeddedFileProvider(Assembly assembly)
    {
        if (assembly == null) throw new ArgumentNullException(nameof(assembly));

        _assembly = assembly;
    }

    public IFileInfo GetFileInfo(string subpath)
    {
        string fullFileName = $"{_assembly.GetName().Name}.{subpath}";

        bool isFileEmbedded = _assembly.GetManifestResourceNames().Contains(fullFileName);

        return isFileEmbedded
          ? new EmbeddedFileInfo(subpath, _assembly.GetManifestResourceStream(fullFileName))
          : (IFileInfo) new NotFoundFileInfo(subpath);
    }

    public IDirectoryContents GetDirectoryContents(string subpath)
    {
        throw new NotImplementedException();
    }

    public IChangeToken Watch(string filter)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

创建易于使用的 AddEmbeddedJsonFile 扩展方法。

public static class ConfigurationBuilderExtensions
{
    public static IConfigurationBuilder AddEmbeddedJsonFile(this IConfigurationBuilder cb,
        Assembly assembly, string name, bool optional = false)
    {
        // reload on change is not supported, always pass in false
        return cb.AddJsonFile(new EmbeddedFileProvider(assembly), name, optional, false);
    }
}
Run Code Online (Sandbox Code Playgroud)