在C#类库中使用IConfiguration

我正在使用C#和Core .NET构建一个类库。 我试图使用config.json文件中的配置。 以下是该文件的内容:

config.json

 { "emailAddress":"someone@somewhere.com" } 

在尝试使用config.json进行配置时,我在我的project.json文件中引用了Microsoft.Framework.ConfigurationModel.Json 。 在我的代码中,我有以下内容:

MyClass.cs

 using Microsoft.Framework.ConfigurationModel; public class MyClass { public string GetEmailAddress() { // return ConfigurationManager.AppSettings["emailAddress"]; This is the approach I had been using since .NET 2.0 return ?; // What goes here? } } 

从.NET 2.0开始,我一直在使用ConfigurationManager.AppSettings["emailAddress"] 。 但是,我现在正试图通过IConfiguration学习如何以新方式实现这一目标。 我的问题是,这是一个类库。 出于这个原因,我不确定配置文件的加载方式,地点或时间。 在传统的.NET中,我只需要为ASP.NET项目命名文件web.config,为其他项目命名app.config。 现在,我不确定。 我有一个ASP.NET MVC 6项目和一个XUnit项目。 所以,我试图弄清楚如何在这两种场景中使用config.json

谢谢!

从未使用它,但快速搜索引导我这…

 var configuration = new Configuration(); configuration.AddJsonFile(“config.json”); var emailAddress = configuration.Get("emailAddress"); 

也许你可以试试。

IMO类库应该与应用程序设置数据无关。 通常,图书馆消费者是关注这些细节的人。 是的,这并非总是如此(例如,如果您有一个进行RSA加密/解密的类,您可能需要一些私有配置来允许私钥生成/存储),但在大多数情况下,这是真的。

因此,通常,尝试将应用程序设置保留在类库之外,并让消费者提供此类数据。 在您的评论中,您提到了数据库的连接字符串。 这是保存在类库之外的数据的完美示例。 该库不应该关心它所要读取的数据库,只需它从一个读取。 下面的例子(如果因为我从内存中动态写这个错误,我道歉):

图书馆

使用连接字符串的库类

 public class LibraryClassThatNeedsConnectionString { private string connectionString; public LibraryClassThatNeedsConnectionString(string connectionString) { this.connectionString = connectionString; } public string ReadTheDatabase(int somePrimaryKeyIdToRead) { var result = string.Empty; // Read your database and set result return result; } } 

应用

appsettings.json

 { "DatabaseSettings": { "ConnectionString": "MySuperCoolConnectionStringWouldGoHere" } } 

DatabaseSettings.cs

 public class DatabaseSettings { public string ConnectionString { get; set; } } 

Startup.cs

 public class Startup { public Startup(IHostingEnvironment env) { Configuration = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables() .Build(); } public IConfigurationRoot Configuration { get; } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { // Setup logging // Configure app } public void ConfigureServices(IServiceCollection services) { // Configure services services.Configure(Configuration.GetSection("DatabaseSettings")); services.AddOptions(); // Register our class that reads the DB into the DI framework services.AddTransient(); } } 

使用库类读取数据库的类

 public interface IInterfaceForClass { string ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead); } public class ClassThatNeedsToReadDatabaseUsingLibrary : IInterfaceForClass { private DatabaseSettings dbSettings; private LibraryClassThatNeedsConnectionString libraryClassThatNeedsConnectionString; public ClassThatNeedsToReadDatabaseUsingLibrary(IOptions dbOptions) { this.dbSettings = dbOptions.Value; this.libraryClassThatNeedsConnectionString = new LibraryClassThatNeedsConnectionString(this.dbSettings.ConnectionString); } public string ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead) { return this.libraryClassThatNeedsConnectionString.ReadTheDatabase(somePrimaryKeyIdToRead); } } 

一些控制器类,用于处理从数据库中读取的UI内容

 public class SomeController : Controller { private readonly classThatReadsFromDb; public SomeController(IInterfaceForClass classThatReadsFromDb) { this.classThatReadsFromDb = classThatReadsFromDb; } // Controller methods } 

TL; DR

尽量避免在类库中使用应用程序设置。 相反,让您的类库与这些设置无关,并让消费者传递这些设置。

编辑:

我在dependency injection中添加了一个控制器类来演示使用dependency injection来构建从DB读取的类。 这使DI系统解决了必要的依赖关系(例如DB选项)。

这是做到这一点的一种方式(也是最好的方式)。 另一种方法是将IOptions注入控制器并手动新建从DB读取并传递选项的类(不是最佳实践,DI是更好的方法)

首先在.csproj文件中添加一个在构建过程中hocks的目标,如果以下内容不符合您的需求,请参阅更多选项的链接,例如发布

    

你可以像下面这样使用它

 using Microsoft.Framework.ConfigurationModel; using Microsoft.Extensions.Configuration; using System; public class MyClass { public string GetEmailAddress() { //For example purpose only, try to move this to a right place like configuration manager class string basePath= System.AppContext.BaseDirectory; IConfigurationRoot configuration= new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("config.json") .Build(); return configuration.Get("emailAddress"); } } 

不知道它是否在core.net库中工作,但在我的mvc6应用程序中,我用这种方式:

 public class Startup { public static IConfigurationRoot Configuration; public Startup(IApplicationEnvironment appEnv) { var builder = new ConfigurationBuilder() .SetBasePath(appEnv.ApplicationBasePath) .AddJsonFile("config.json") .AddEnvironmentVariables(); Configuration = builder.Build(); } } 

那么如果我需要在整个应用程序中调用config.jason中的信息,我会这样做:即在控制器方法中:

 var email = Startup.Configuration["AppSettings:SiteEmailAddress"]; 

我的WonderContext类中的sql字符串:

 var connString = Startup.Configuration["AppSettings:WonderContextConnection"];