在 C# Class 库中使用 IConfiguration
Using IConfiguration in C# Class Library
我正在使用 C# 和 Core .NET 构建一个 class 库。我正在尝试使用 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
学习如何以新的方式进行操作。我的问题是,这是一个 class 库。出于这个原因,我不确定如何、在何处或何时加载配置文件。在传统的 .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 class 库应该与应用程序设置数据无关。通常,图书馆消费者是关心这些细节的人。是的,这并不总是正确的(例如,如果您有一个执行 RSA encryption/decryption 的 class,您可能需要一些私有配置以允许使用私钥 gen/storage),但是对于大部分是真的。
因此,一般来说,尽量让应用程序设置远离 class 库,并让消费者提供此类数据。在您的评论中,您提到了数据库的连接字符串。这是将数据保存在 class 库之外的完美示例。图书馆不应该关心它调用什么数据库来读取,只需要从一个数据库读取。下面的例子(如果有一些错误,我很抱歉,因为我是凭记忆写的):
图书馆
使用连接字符串的库class
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<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
services.AddOptions();
// Register our class that reads the DB into the DI framework
services.AddTransient<IInterfaceForClass, ClassThatNeedsToReadDatabaseUsingLibrary>();
}
}
Class使用库class读取数据库
public interface IInterfaceForClass
{
string ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead);
}
public class ClassThatNeedsToReadDatabaseUsingLibrary : IInterfaceForClass
{
private DatabaseSettings dbSettings;
private LibraryClassThatNeedsConnectionString libraryClassThatNeedsConnectionString;
public ClassThatNeedsToReadDatabaseUsingLibrary(IOptions<DatabaseSettings> dbOptions)
{
this.dbSettings = dbOptions.Value;
this.libraryClassThatNeedsConnectionString = new LibraryClassThatNeedsConnectionString(this.dbSettings.ConnectionString);
}
public string ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead)
{
return this.libraryClassThatNeedsConnectionString.ReadTheDatabase(somePrimaryKeyIdToRead);
}
}
一些控制器 class 处理 UI 从数据库中读取的内容
public class SomeController : Controller
{
private readonly classThatReadsFromDb;
public SomeController(IInterfaceForClass classThatReadsFromDb)
{
this.classThatReadsFromDb = classThatReadsFromDb;
}
// Controller methods
}
TL;DR
尽量避免在 class 库中使用应用程序设置。相反,让您的 class 库对此类设置不可知,并让消费者传递这些设置。
编辑:
我将依赖注入添加到控制器中 class 以演示使用依赖注入构建从数据库读取的 class。这让 DI 系统解决必要的依赖关系(例如 DB 选项)。
这是一种方法(也是最好的方法)。另一种方法是将 IOptions 注入控制器并手动更新从数据库读取的 class 并将选项传入(不是最佳实践,DI 是更好的方法)
首先在您的 .csproj
文件中添加一个 ,如果以下内容不符合您的需要,请参阅 link 以获得更多选项,例如发布
<Target Name="AddConfig" AfterTargets="AfterBuild">
<Copy SourceFiles="config.json" DestinationFolder="$(OutDir)" />
</Target>
你可以像下面这样使用它
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");
}
}
这应该有效。需要安装包 Microsoft.Extensions.Configuration.Json
public static class Config
{
private static IConfiguration configuration;
static Config()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
configuration = builder.Build();
}
public static string Get(string name)
{
string appSettings = configuration[name];
return appSettings;
}
}
您还可以设置 class 库的属性,方法是右键单击 .csproject -> 属性 -> 设置 -> 在右侧 window 添加一个新的 属性 .
确保在访问修饰符下拉列表中将 select 访问修饰符设为 public。
现在,将 class 库项目引用添加到您的 .net 核心项目。
Create appSettings.cs class as mentioned below
public class AppSettings
{
public string MyConnectionString { get; set; }
}
Set key-value appSettings.json
"AppSettings": {
"MyConnectionString": "yourconnectionstring",
},
Now, we just need to get connection string from appSettings.json and
set properties into class library in Startup.cs as below.
// This method gets called by the runtime. Use this method to add services to the container
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// inject App setting
var appSettingSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingSection);
var appsetting = appSettingSection.Get<AppSettings>();
// set connection string in .csproject properties.
classLibraryProject.Properties.Settings.Default.Properties["MyConnectionString"].DefaultValue = appsetting.MyconnectionString;
}
注:
- 确保 MyConnectionString 键。在所有三个文件中应该相同。
- 确保在 ClassLibrary 项目中将访问修饰符设置为 Public。
希望对您有所帮助。
如何使用 IConfiguration 将 AppSettings.Json 键值读取到 C# 控制器中。
以防有人想看Asp.net Core .Net 5.0 示例。我已经完成了上述答案并为我的应用程序稍微调整了我的代码。
如果您想了解如何将其用于控制台应用程序,请访问我对此 的回答,我还添加了带有电子邮件地址的示例。
我的 AppSettings.Json 是:
{
"AppSettings": {
"FTPLocation": "\\hostname\\c$\\FTPMainFolder\\ftpFolder\\Test\",
"FTPUri": "ftp://hostname.domainname.com/foldername/",
"CSVFileName": "Test Load Planning.csv"
},
"ConnectionStrings":
{
"AppDbConnString": "Server=sqlserverhostname.domainname.com;Database=DBName;Trusted_Connection=True; MultipleActiveResultSets=true" },
"ADSecurityGroups": { "UserSecurityGroups": "AD-DL-GROUP-NAME;AD-DL-GROUP2-NAME"},
"Logging":
{
"LogLevel": {
"Default": "Warning"
}
}
}
我的LoginController.cs是:
using Microsoft.Extensions.Configuration;
public class LoginController : BaseController
{
private readonly ILoginDataServices _loginDataServices;
private readonly IConfiguration _configuration;
public IActionResult Index()
{
return View();
}
public LoginController(ILoginDataServices loginDataServices, IConfiguration configuration)
{
_loginDataServices = loginDataServices;
_configuration = configuration;
}
public bool CheckLogin(string userName, string password)
{
if (CheckIfValidEmployee(userName))
{
//////checking code here....
}
else
{
return false;
}
}
bool CheckIfValidEmployee(string userName)
{
var securityGroups = _configuration.GetSection("ADSecurityGroups:UserSecurityGroups").Value.Split(';');
Console.WriteLine(securityGroups);
////////Code to check user exists into security group or not using variable value
}
我正在使用 C# 和 Core .NET 构建一个 class 库。我正在尝试使用 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
学习如何以新的方式进行操作。我的问题是,这是一个 class 库。出于这个原因,我不确定如何、在何处或何时加载配置文件。在传统的 .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 class 库应该与应用程序设置数据无关。通常,图书馆消费者是关心这些细节的人。是的,这并不总是正确的(例如,如果您有一个执行 RSA encryption/decryption 的 class,您可能需要一些私有配置以允许使用私钥 gen/storage),但是对于大部分是真的。
因此,一般来说,尽量让应用程序设置远离 class 库,并让消费者提供此类数据。在您的评论中,您提到了数据库的连接字符串。这是将数据保存在 class 库之外的完美示例。图书馆不应该关心它调用什么数据库来读取,只需要从一个数据库读取。下面的例子(如果有一些错误,我很抱歉,因为我是凭记忆写的):
图书馆
使用连接字符串的库class
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<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
services.AddOptions();
// Register our class that reads the DB into the DI framework
services.AddTransient<IInterfaceForClass, ClassThatNeedsToReadDatabaseUsingLibrary>();
}
}
Class使用库class读取数据库
public interface IInterfaceForClass
{
string ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead);
}
public class ClassThatNeedsToReadDatabaseUsingLibrary : IInterfaceForClass
{
private DatabaseSettings dbSettings;
private LibraryClassThatNeedsConnectionString libraryClassThatNeedsConnectionString;
public ClassThatNeedsToReadDatabaseUsingLibrary(IOptions<DatabaseSettings> dbOptions)
{
this.dbSettings = dbOptions.Value;
this.libraryClassThatNeedsConnectionString = new LibraryClassThatNeedsConnectionString(this.dbSettings.ConnectionString);
}
public string ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead)
{
return this.libraryClassThatNeedsConnectionString.ReadTheDatabase(somePrimaryKeyIdToRead);
}
}
一些控制器 class 处理 UI 从数据库中读取的内容
public class SomeController : Controller
{
private readonly classThatReadsFromDb;
public SomeController(IInterfaceForClass classThatReadsFromDb)
{
this.classThatReadsFromDb = classThatReadsFromDb;
}
// Controller methods
}
TL;DR
尽量避免在 class 库中使用应用程序设置。相反,让您的 class 库对此类设置不可知,并让消费者传递这些设置。
编辑:
我将依赖注入添加到控制器中 class 以演示使用依赖注入构建从数据库读取的 class。这让 DI 系统解决必要的依赖关系(例如 DB 选项)。
这是一种方法(也是最好的方法)。另一种方法是将 IOptions 注入控制器并手动更新从数据库读取的 class 并将选项传入(不是最佳实践,DI 是更好的方法)
首先在您的 .csproj
文件中添加一个
<Target Name="AddConfig" AfterTargets="AfterBuild">
<Copy SourceFiles="config.json" DestinationFolder="$(OutDir)" />
</Target>
你可以像下面这样使用它
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");
}
}
这应该有效。需要安装包 Microsoft.Extensions.Configuration.Json
public static class Config
{
private static IConfiguration configuration;
static Config()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
configuration = builder.Build();
}
public static string Get(string name)
{
string appSettings = configuration[name];
return appSettings;
}
}
您还可以设置 class 库的属性,方法是右键单击 .csproject -> 属性 -> 设置 -> 在右侧 window 添加一个新的 属性 . 确保在访问修饰符下拉列表中将 select 访问修饰符设为 public。
现在,将 class 库项目引用添加到您的 .net 核心项目。
Create appSettings.cs class as mentioned below
public class AppSettings
{
public string MyConnectionString { get; set; }
}
Set key-value appSettings.json
"AppSettings": {
"MyConnectionString": "yourconnectionstring",
},
Now, we just need to get connection string from appSettings.json and set properties into class library in Startup.cs as below.
// This method gets called by the runtime. Use this method to add services to the container
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// inject App setting
var appSettingSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingSection);
var appsetting = appSettingSection.Get<AppSettings>();
// set connection string in .csproject properties.
classLibraryProject.Properties.Settings.Default.Properties["MyConnectionString"].DefaultValue = appsetting.MyconnectionString;
}
注:
- 确保 MyConnectionString 键。在所有三个文件中应该相同。
- 确保在 ClassLibrary 项目中将访问修饰符设置为 Public。
希望对您有所帮助。
如何使用 IConfiguration 将 AppSettings.Json 键值读取到 C# 控制器中。
以防有人想看Asp.net Core .Net 5.0 示例。我已经完成了上述答案并为我的应用程序稍微调整了我的代码。
如果您想了解如何将其用于控制台应用程序,请访问我对此
我的 AppSettings.Json 是:
{
"AppSettings": {
"FTPLocation": "\\hostname\\c$\\FTPMainFolder\\ftpFolder\\Test\",
"FTPUri": "ftp://hostname.domainname.com/foldername/",
"CSVFileName": "Test Load Planning.csv"
},
"ConnectionStrings":
{
"AppDbConnString": "Server=sqlserverhostname.domainname.com;Database=DBName;Trusted_Connection=True; MultipleActiveResultSets=true" },
"ADSecurityGroups": { "UserSecurityGroups": "AD-DL-GROUP-NAME;AD-DL-GROUP2-NAME"},
"Logging":
{
"LogLevel": {
"Default": "Warning"
}
}
}
我的LoginController.cs是:
using Microsoft.Extensions.Configuration;
public class LoginController : BaseController
{
private readonly ILoginDataServices _loginDataServices;
private readonly IConfiguration _configuration;
public IActionResult Index()
{
return View();
}
public LoginController(ILoginDataServices loginDataServices, IConfiguration configuration)
{
_loginDataServices = loginDataServices;
_configuration = configuration;
}
public bool CheckLogin(string userName, string password)
{
if (CheckIfValidEmployee(userName))
{
//////checking code here....
}
else
{
return false;
}
}
bool CheckIfValidEmployee(string userName)
{
var securityGroups = _configuration.GetSection("ADSecurityGroups:UserSecurityGroups").Value.Split(';');
Console.WriteLine(securityGroups);
////////Code to check user exists into security group or not using variable value
}