从 .NET 标准库读取 appsettings.json

18
我正在使用.NET Core框架启动一个新的RESTful项目。
我将我的解决方案分成两个部分:Framework(一组.NET标准库)和Web(RESTful项目)。
在Framework文件夹中,我提供了一些库以供进一步的Web项目使用,并希望提供一个配置类,其中包含通用方法T GetAppSetting<T>(string Key)
我的问题是:如何在.NET Standard中访问AppSettings.json文件?
我找到了很多关于读取此文件的示例,但所有这些示例都将文件读取到Web项目中,没有一个示例将其读取到外部库中。 我需要可重用的代码来供其他项目使用。

4
请不要再这样做。不要试图从libraries中直接读取配置信息。配置类应该作为依赖项注入。您的程序集应该定义配置类并包含配置设置代码,以将它们与设置匹配(例如configurationBuilder.Configure<MySettingsClas>()),但是实际读取配置信息的工作应该留给主应用程序来完成。 - Panagiotis Kanavos
请注意,您正在将.NET Standard库与.NET Core Web项目耦合在一起,因为您想读取特定于这些项目的json文件。通常,您会将配置传递给库,而不是反过来。 - BgrWorker
顺便提一下,app.config 在 程序集 上从未起作用过。设置定义了默认值和从应用程序的 app.config 中加载它们的模式。您无法通过修改程序集的 app.config 来更改设置,而是必须更改默认值。 - Panagiotis Kanavos
@BgrWorker,没有耦合。实际上,耦合已经被移除了。主应用程序可以是任何东西:Microsoft.Extensions.Configuration、DI、Logging都是.NET Standard 2.0程序集,可以在任何运行时使用。我也在我的完整框架应用程序中使用它们。 - Panagiotis Kanavos
@PanagiotisKanavos 我指的是问题,而不是你的评论,事实上你的评论是正确的(我也点了赞)。 - BgrWorker
@PanagiotisKanavos 那我需要从我的 .net core 项目中读取 JSON 配置,然后使用 DI 将配置注入到我的库中吗? - Lollo
2个回答

21

正如评论中已经提到的,你真的不应该这样做。而是应该使用依赖注入来注入已配置的 IOptions<MyOptions>

但是,你仍然可以将 JSON 文件作为配置加载:

IConfiguration configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory()) // Directory where the json files are located
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .Build();

// Use configuration as in every web project
var myOptions = configuration.GetSection("MyOptions").Get<MyOptions>();

请确保引用Microsoft.Extensions.ConfigurationMicrosoft.Extensions.Configuration.Json包。有关更多配置选项,请参阅文档


2
好的解决方案,谢谢!不过我已经明白为什么不应该这样做了... :D - Lollo
4
为了让这段代码能够构建,我必须添加三个 NuGet 包:Microsoft.Extensions.Configuration、Microsoft.Extensions.Configuration.Binder 和 Microsoft.Extensions.Configuration.Json。 - goPlayerJuggler
在这种情况下,如果您还想支持UserSecrets怎么办?我尝试通过添加AddUserSecrets(Assembly.GetEntryAssembly())来实现,但显然没有任何区别。有什么想法可以让它在这个上下文中工作吗? - Thomas Purrer
从我的角度来看,这个问题可以通过使用UserSecrets轻松解决。在这里顺序很重要!首先调用AddJsonFile,然后再调用AddUserSecrets。答案在这里:在调用AddJsonFile()之前调用AddUserSecrets() - Thomas Purrer
这段代码不适用于 .net standard 2.0 版本。不确定它是否适用于 .net core。 - Ashutosh Kumar
1
@goPlayerJuggler 非常感谢您解释了在.NET Standard中所需的额外包。这些在任何文档或回答中都没有提到。直到我看到了您的评论,才知道这一点。当微软的库很少告诉您需要哪些额外的库才能使它们正常工作,并且它们也不包含在任何依赖列表中时,尝试使用微软库变得非常令人沮丧。 - Bryan Williams

2

我扩展了这个场景,以便还可以管理(可选的)用户机密(来自包:Microsoft.Extensions.Configuration.UserSecrets):

IConfiguration configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory()) // Directory where the json files are located
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddUserSecrets(Assembly.GetEntryAssembly(),optional:true);
    .Build();

添加Json文件和用户密钥的顺序很重要。请参见调用AddJsonFile和AddUserSecrets
我完全同意这不是首选方式(而应该使用IOptions<>依赖注入(Dependency Injection),并让应用程序配置库)。但我提到这个是因为我正在处理一个(非常老的)读取app.config (xml) 的库。这个库无法从应用程序中进行配置,而是直接进行配置(期望在app.config中提供值)。现在这个库用于Full Framework、.NET Core和.NET5(或更新)应用程序。所以我也必须支持appsettings.json。实际上无法以一种使应用程序能够向库提供必要配置值的方式来适应库。因此我添加了对JSON的支持(暂时如此——以后我们可以花费更多精力来使其可由应用程序进行配置)
最后我还支持环境(environments),我的代码看起来像这样:
var builder = new ConfigurationBuilder()
                      .SetBasePath(Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
            
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (!string.IsNullOrEmpty(environment))
{
    builder = builder.AddJsonFile(string.Format("appsettings.{0}.json", environment), optional: true, reloadOnChange: false);
    if (string.Equals(environment, "Development", StringComparison.CurrentCultureIgnoreCase))
    {
        builder = builder.AddUserSecrets(Assembly.GetEntryAssembly(),optional:true);
    }
}

请注意,我决定仅为“开发”范围管理“用户机密”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接