不使用 ASP.NET Core 时如何使用 C# 中的配置?

Dra*_*ex_ 3 c#

我正在使用 .NET Core 3.1。

Microsoft 提供了有关如何使用 ASP.NET 配置的综合指南。但是,我找不到有关如何在不使用 ASP.NET 的 .NET Core 应用程序中使用配置的任何指南。

如何从 C# 控制台应用程序访问配置文件?

gra*_*der 7

两者之间没有太大区别(它在 dotnet-core“应用程序”中的工作方式与在 aspnet-core 中的工作方式)。

现在,我假设您不只是想 console.write 出这些值,但您最终会希望在一些真实代码中访问它们......下面使用“UserController”作为需要访问您的配置值的代码。

好的,dotnet core 的最大特点是您可以将配置(通常是 POCO 类)(有关更多选项,请参阅本答案后面的 IOptions)注入到需要配置的代码中。您不会像在 dotnet 框架中那样“从 app.config 或 web.config 获取值”。 请重新阅读该内容并用它来改变您对 dotnet-framework 的想法。我怎么强调都不为过。您需要配置值的“真实代码”不应该出去读取文件......您应该poco (或IOptions<MyPoco>)注入您的类中。

这是我在 dotnet core 控制台应用程序中执行的典型设置。

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

public static class Program
{
    public static int Main(string[] args)
    {
        try
        {
            /* look at the Project-Properties/Debug(Tab) for this environment variable */
            string environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
            Console.WriteLine(string.Format("DOTNET_ENVIRONMENT='{0}'", environmentName));
            Console.WriteLine(string.Empty);

            IConfigurationBuilder builder = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json")
                    .AddJsonFile($"appsettings.{environmentName}.json", true, true)
                    .AddEnvironmentVariables();
            /* pay attention to the "true, true" arguments above, they reflect optional: true, reloadOnChange: true ..  "optional" being the important one here */


            IConfigurationRoot myconfig = builder.Build();

            IServiceProvider servicesProvider = BuildDi(myconfig );
            using (servicesProvider as IDisposable)
            {
                /* now do something with your properly composed IoC container */

                /* maybe something like this...*/
                IUserController uc = servicesProvider.GetRequiredService<IUserController>();

                 /* UserController will have the email-config injected into it, because you did the IoC container setup correctly in "BuildDi" method .. later in this answer */

                Console.WriteLine("Press ANY key to exit");
                Console.ReadLine();
            }
Run Code Online (Sandbox Code Playgroud)

===========================

那么,那条线是什么

.AddJsonFile($"appsettings.{environmentName}.json"
Run Code Online (Sandbox Code Playgroud)

所有关于?

首先,它是可选的。您不必使用它。但我将其包含在这个答案中以提供整体答案。(如果您不想使用它,只需删除或注释掉代码行 '.AddJsonFile($"appsettings.{environmentName}.json", true, true)'。

其次,这是最佳实践吗?唔。对于发展来说还不错。但是您是否希望在 .json 文件中保留生产配置值的秘密?该讨论超出了原始问题和此答案的范围。

但如果你(决定)使用它。

有一个神奇的环境变量来驱动事物。

我发现 .net core 控制台应用程序有不同名称的少数几个地方之一是:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.1

所以对于 ASP.NET Core 应用程序,我设置

ASPNETCORE_ENVIRONMENT 
Run Code Online (Sandbox Code Playgroud)

对于 dotnet core 控制台应用程序,我设置

DOTNET_ENVIRONMENT
Run Code Online (Sandbox Code Playgroud)

===========

因此,对于上述内容,您必须至少有一个“appsettings.json”文件。

但您可以选择拥有这些文件。

appsettings.Development.json
appsettings.Staging.json
appsettings.Production.json
Run Code Online (Sandbox Code Playgroud)

您可以在这里阅读有关这些内容的更多信息: https: //andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/

现在,如何将 .json 文件中的这些值获取到需要它们的代码中。

在 dotnet-core 中,配置 poco 通常被注入到类中。

https://medium.com/@dozieogbo/a-better-way-to-inject-appsettings-in-asp-net-core-96be36ffa22b

上面展示了一个很好的例子......

=======================

public class EmailConfig {
    public string Username { get; set;}  
    public string Password { get; set;} 
}
Run Code Online (Sandbox Code Playgroud)

=======================

public class UserController : IUserController
{
    private readonly EmailConfig _emailConfig;

    public UserController(EmailConfig emailConfig)
    {
        _emailConfig = emailConfig;
    
        //_emailConfig.Username
        //_emailConfig.Password
    }
}
Run Code Online (Sandbox Code Playgroud)

并且 .json 将附加额外的自定义配置部分/区域......按照相同的示例,下面显示默认的 .json 文件......但添加了“电子邮件”部分。

"ConnectionStrings": {
  "DefaultConnection": ""
},
"Logging": {
  "IncludeScopes": false,
  "LogLevel": {
    "Default": "Warning"
  }
},
"Email": {
  "Username": "peanut",
  "Password": "butter"
}
Run Code Online (Sandbox Code Playgroud)

=======================

=======================

    private static IServiceProvider BuildDi(IConfiguration myconfig)
    {


        ////setup our DI
        IServiceCollection servColl = new ServiceCollection()
            .AddLogging();  /* do any other stuff here that is extension method */


        EmailConfig emailConfig = new EmailConfig();
        myconfig.GetSection("Email").Bind(emailConfig);
        /* you may want to check for null here on emailConfig */
    
        //Create singleton from instance..and push to the IoC container
        servColl.AddSingleton<EmailConfig>(emailConfig);

         /* not shown here.. but you'll need to add IUserController,UserController as well */

        ServiceProvider servProv = servColl.BuildServiceProvider();

        return servProv;
    }
Run Code Online (Sandbox Code Playgroud)

以及密切相关的 csproj 值。

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.*" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.*" />
  </ItemGroup>
Run Code Online (Sandbox Code Playgroud)

现在奖励材料

https://medium.com/@kmar.ayush/eli5-ioptions-vs-ioptionssnaphot-vs-ioptionsmonitor-fab1d7e26a75

或者互联网搜索“ioptions vs ioptionssnaphot vs ioptionsmonitor”

您还可以使用上述“选项”之一来设置 POCO 配置。

IOptions<T>
When using this, the values will always be same for the lifetime of the application. Changing the value of the appsettings file while the application is running will not make any difference to the value when using IOptions. In other words it is in Singleton scope.

IOptionsSnapshot<T>
Using this will always give you the most up to date values in your config file for every request and will remain the same for the during of your request.


IOptionsMonitor<T>
Using the monitor is almost like having real time access to your settings file. Each time you need the value from the config, it will read it and evaluate whatever is there and return that.
Run Code Online (Sandbox Code Playgroud)

......................

将 Poco 配置对象注入到“真实代码”中的优点之一是,对于单元测试来说,EmailConfig 可以“编码”而无需备份 .config/.json 文件)。也就是说,您可以在不需要 json 文件的情况下测试代码......并完全在内存中运行测试。


最后,这是一个小示例,展示了在未设置环境变量时如何实际“获取”“默认值为“生产””值:

    public static class Program
    {
        static void Main(string[] args)
        {

            string environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
            Console.WriteLine(string.Format("DOTNET_ENVIRONMENT='{0}'", environmentName));
            Console.WriteLine(string.Empty);

            environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            Console.WriteLine(string.Format("ASPNETCORE_ENVIRONMENT='{0}'", environmentName));
            Console.WriteLine(string.Empty);


            /* both empty strings above */

            Microsoft.Extensions.Hosting.HostBuilder builder = new Microsoft.Extensions.Hosting.HostBuilder();
            builder
            .ConfigureHostConfiguration(config =>
            {
                config.AddEnvironmentVariables(prefix: "DOTNETCORE_");
            })
             .ConfigureAppConfiguration((context, config) =>
             {
                 config.AddJsonFile("appsettings.json", optional: true);
                 config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
             });


            Microsoft.Extensions.Hosting.IHost hst = builder.Build();

            /* do NOT do the below in real code..this is cheap trick to show EnvironmentName default */
            Microsoft.Extensions.Hosting.IHostEnvironment env = hst.Services.GetService(typeof(Microsoft.Extensions.Hosting.IHostEnvironment)) as Microsoft.Extensions.Hosting.IHostEnvironment;
            if (null != env)
            {
                Console.WriteLine(env.EnvironmentName);
            }
}
Run Code Online (Sandbox Code Playgroud)

和相关的 csproj 零件

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.*" />
    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.*" />

  </ItemGroup>
Run Code Online (Sandbox Code Playgroud)

输出:

DOTNET_ENVIRONMENT=''

ASPNETCORE_ENVIRONMENT=''

Production
Run Code Online (Sandbox Code Playgroud)


Aus*_*Joe 6

.NET Core 中没有内置配置功能(显然)。您需要使用 Nuget 和一些启动配置来注入它。基本上,您需要注册您的配置。这是如何...

安装 NuGet 包:

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package Microsoft.Extensions.Configuration.CommandLine
Install-Package Microsoft.Extensions.Configuration.EnvironmentVariables 
Run Code Online (Sandbox Code Playgroud)

appsettings.json在根级别将文件添加到您的项目。您需要像这样注册它:

static async Task Main(string[] args)
{

  IConfiguration Configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables()
    .AddCommandLine(args)
    .Build();
}
Run Code Online (Sandbox Code Playgroud)

现在您的提供程序已在您的控制台应用程序中注册,您可以像这样引用您的配置:

var section = Configuration.GetSection("MySectionOfSettings");
var configValue = Configuration.GetValue("MySetting");
Run Code Online (Sandbox Code Playgroud)