在 C# 类库中使用 IConfiguration

本文关键字:IConfiguration 类库 | 更新日期: 2023-09-27 18:37:13

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

config.json

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

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

我的班级.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

谢谢!

在 C# 类库中使用 IConfiguration

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"
  }
}

数据库设置.cs

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

启动.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>();
    }
}

使用库类读取数据库的类

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);
    }
}

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

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

博士

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

编辑:

我将依赖关系注入添加到控制器类中,以演示如何使用依赖关系注入来构建从数据库读取的类。这允许 DI 系统解决必要的依赖关系(例如数据库选项)。

这是一种方法(也是最好的方法)。另一种方法是将 IOptions 注入控制器并手动更新从数据库读取的类并传入选项(不是最佳实践,DI 是更好的方法)

同时支持 appSettings.json

和 appSettings.Development.json:

配置类实现:

using Microsoft.Extensions.Configuration;
using System.IO;
public static class Config
{
    private static IConfiguration configuration;
    static Config()
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appSettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile("appSettings.Development.json", optional: true, reloadOnChange: true);
        configuration = builder.Build();
    }
    public static string Get(string name)
    {
        string appSettings = configuration[name];
        return appSettings;
    }
    public static IConfigurationSection GetSection(string name)
    {
        return configuration.GetSection(name);
    }
}

配置类用法:

部分

var cosmosDb = new CosmosDbProviderConfiguration();
Config.GetSection(CosmosDbProviderConfiguration.CosmosDbProvider).Bind(cosmosDb);

钥匙

var email = Config.Get("no-reply-email");

从未使用过它,但快速搜索将我引导到这个......

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

也许你可以试试。

首先在.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");
    }
}

.NET 6.0+ 中,这是我找到的用于获取实体框架的连接字符串的解决方案。查找正确的 nuget 包(Microsoft.Extensions.Configuration.Json) 时存在一些问题。希望这能为大家省去一些麻烦。

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; 
//nuget package: Microsoft.Extensions.Configuration.Json
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        var path = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
        var builder = new ConfigurationBuilder();
        builder.AddJsonFile(path);
        var root = builder.Build();
        var connectionString = root.GetSection("ConnectionStrings").GetSection("DefaultConnection").Value;
        optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
    }
}

还可以通过右键单击 .csproject -> 属性->设置->在右侧窗口中添加新属性来设置类库的属性。请确保在"访问修饰符"下拉列表中选择"访问修饰符"作为"公共"。

现在,将类库项目引用添加到 .net 核心项目。

创建应用设置.cs类,如下所述

public class AppSettings
{
    public string MyConnectionString { get; set; }
}
设置

键值应用设置.json

"AppSettings": {
"MyConnectionString": "yourconnectionstring",

},

现在,我们只需要从appSettings.json获取连接字符串,并且将属性设置为"启动"中的类库中.cs如下所示。

// 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 密钥。它在所有三个文件中都应该相同。
  • 确保在类库项目中将"访问修饰符"设置为"公共"。

我希望这可能会有所帮助。

如何使用 IConfiguration 将 AppSettings.Json 键值读取到 C# 控制器中。

如果有人想看它,Asp.net Core .Net 5.0 示例。我已经浏览了上述答案,并为我的应用程序稍微调整了我的代码。

如果您想了解如何将其用于控制台应用程序,请访问此链接上的我的答案,我还添加了带有电子邮件地址的示例。

<小时 />

My 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"    
       }  
   }
}
<小时 />

我的登录控制器.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
     }