繁体   English   中英

在控制台应用程序中从另一个 class 调用 appsettings.json 数据

[英]Calling appsettings.json data from another class in a console app

以下是Microsoft 文档中的示例代码,它显示了如何在控制台应用程序中使用 appsettings.json

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleJson.Example
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) =>
                {
                    configuration.Sources.Clear();

                    IHostEnvironment env = hostingContext.HostingEnvironment;

                    configuration
                        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);

                    IConfigurationRoot configurationRoot = configuration.Build();

                    TransientFaultHandlingOptions options = new();
                    configurationRoot.GetSection(nameof(TransientFaultHandlingOptions))
                                     .Bind(options);

                    Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
                    Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
                });
    }
}

我需要在另一个 class的方法中获取配置值,如下所示。 我想我需要使用依赖注入并将IConfigurationRoot发送到myClass如此链接所示,但无法弄清楚到底如何?

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleJson.Example
{
    class Program
    {
        static void Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            IDatabase db = xyz.GetDatabase();

            ConfigureServices.Initialize(db);
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) =>
                {
                    configuration.Sources.Clear();

                    IHostEnvironment env = hostingContext.HostingEnvironment;

                    configuration
                        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);

                    IConfigurationRoot configurationRoot = configuration.Build();

                    TransientFaultHandlingOptions options = new();
                    configurationRoot.GetSection(nameof(TransientFaultHandlingOptions))
                                     .Bind(options);

                    
                });
    }

    class ConfigureServices
    {   public static void Initialize(IDatabase db)
        {
             Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
             Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");

        }
    }
}

所以,我需要从appsettings.json获取值并在我的 Initialize 方法中使用它们。 我可以通过对值进行硬编码来使用代码的 rest。

我尝试在 ConfigureAppConfiguration 之后添加以下行,但它无法识别configurationRoot

.ConfigureServices((_, services) =>services.AddSingleton<IConfigurationRoot>(configurationRoot));

真诚感谢所有帮助。 谢谢

您可以尝试将 IOptions 模式从 .NET 核心注入到您的 class 中。

执行以下操作:

假设你的 appSettings.json 如下图所示:

"AppSettings": {
    "AppValue": "1"
 }

创建一个 class 来保存您的配置值:

public class AppConfiguration
{
    public AppConfiguration() { } 
    public string AppValue { get; set; } 
}

在您的 Startup.cs 中,将配置 class 添加到服务集合中,如下所示:

using Microsoft.Extensions.Configuration;

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppConfiguration>(Configuration.GetSection("AppSettings"));
    …
}

在您的 class 中,将 IOptions 注入 class。 为配置分配一个内部变量。 参考 class 中的配置数据并获取设置属性:

using Microsoft.Extensions.Options;

…

public class MyService: IMyService
{
    private readonly IOptions<AppConfiguration> _appConfiguration;

    public MyService(..., IOptions<AppConfiguration> appConfiguration, …)
    {
       ...
       _appConfiguration = appConfiguration;
    }

    public SomeTask()   
    {
        // Do something with _appConfiguration.Value.AppValue; 
    }
}

这将允许您的自定义类从您的 appSettings.json 获取值。

此外,对于您的应用程序构建器,建议您的应用程序管道使用启动 class,如下所示:

Host.CreateDefaultBuilder(args)
   .UseStartup<Startup>();

那么你的 Startup class 应该有以下方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
}

public void ConfigureServices(IServiceCollection services)
{
}

当你创建一个新的 .NET Core Web App 时,可以重新生成一个类似的骨架启动 class。 试试上面的,让我知道它是怎么回事。

这里的一切都可以通过在控制台中适当地配置主机来完成。

由于没有提供您正在尝试做的事情的正确表示,我将不得不根据您的示例中实际提供的内容做出一些假设。

首先将您的类重构为实例并尽量避免 static 耦合,以便可以正确使用依赖注入

public class ConfigureServices {
    private readonly TransientFaultHandlingOptions options;
    private readonly IDatabase db;
    
    public ConfigureServices(TransientFaultHandlingOptions options, IDatabase db) {
        this.options = options;
        this.db = db;
    }

    public void Initialize() {
    
         Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
         Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");

        //... access db and options as needed here
    }
}

查看以下评论以了解主机的构建方式。

class Program {
    static void Main(string[] args) {
        using IHost host = CreateHostBuilder(args).Build();

        ConfigureServices config = host.Services.GetRequiredService<ConfigureServices>();
        config.Initialize();
        
        host.Run();
    }

    static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, configuration) => {
                configuration.Sources.Clear();

                IHostEnvironment env = hostingContext.HostingEnvironment;

                configuration
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
                    
                //After this delegate has been invoked, the configuration
                //will be built and added to the HostBuilderContext
            })
            .ConfigureServices((hostingContext, services) => {
                //Get built configuration from the host builder context
                IConfiguration configuration = hostingContext.Configuration;
            
                //Extract the options from configuration.
                TransientFaultHandlingOptions options = configuration
                    .GetSection(nameof(TransientFaultHandlingOptions))
                    .Get<TransientFaultHandlingOptions>();
                    
                //And add it to services so it can be injected as needed
                services.AddSingleton<TransientFaultHandlingOptions>(_ => options);

                //Add IDatabase so it to can be injected and resolved as needed.
                services.AddScoped<IDatabase>(_ => xyz.GetDatabase());
            });
}

将所有必要的依赖项添加到主机后,如上所示解析所需的服务

//...

ConfigureServices config = host.Services.GetRequiredService<ConfigureServices>();
config.Initialize();

//...

真的没有必要手动传递参数。

甚至手动调用ConfigureServices.Initialize()也可能被注入到IHostedService中,并且会在主机启动时为您调用它。

public class DatabaseInitializeService: BackgroundService {
    private readonly ConfigureServices config;
    
    public DatabaseInitializeService(ConfigureServices config) {
        this.config = config;
    }
    
    protected override Task ExecuteAsync(CancellationToken stoppingToken) {
        config.Initialize();
        
        return Task.CompletedTask;
    }    
}

托管服务将添加到ConfigureServices扩展中

//...

services.AddHostedService<DatabaseInitializeService>();

//...

和以前一样简化了Main方法。

static void Main(string[] args) {
    using IHost host = CreateHostBuilder(args).Build();

    host.Run();
}

我有类似的情况。 我想将 AppSettings.Json 自定义密钥访问到我的 asp.net 核心 mvc 项目的 controller 中。 我正在分享可能对您有帮助的控制台应用程序示例代码。

我使用了标准的 VS 2019 控制台应用程序模板和 asp.net 核心,目标为 .net 5.0。

如何将 AppSettings.Json(特定)键值读入 C# 控制台应用程序。


我的项目文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.6" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
    <PackageReference Include="Serilog" Version="2.10.0" />
    <PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
    <PackageReference Include="Serilog.Sinks.MSSqlServer" Version="5.6.0" />
  </ItemGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

我的 AppSettings.Json 是:

  {
  "AppSettings": {

    "FTPLocation": "\\\\FTPHostname\\\\c$\\\\Folder\\\\ftpSite\\\\Prod\\",
    "FTPUri": "ftp://ftphostname/myFolder/",
    "CSVFileName": "TestData.csv",
    },
  "ConnectionStrings": {
    "AppDbConnString": "Server=sqlserverhost.domain.com;Database=DBName; Trusted_Connection=True; MultipleActiveResultSets=true"
    ,
"IdentityConnection": "Server=hostname.domain.com;Database=IdentityDBName; Trusted_Connection=True; MultipleActiveResultSets=true"
      },  
    "EmailAddresses": [
          "email1@test.com",
          "email2@test.com",
          "email3@test.com"
        ],  
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      }
 }

我的 Program.cs 是:

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Microsoft.Extensions.Logging;
using System.IO;

namespace AppSettingsExample
{
    class Program
    {
        public static IConfigurationRoot configuration;
        static void Main(string[] args)
        {
            ServiceCollection serviceDescriptors = new ServiceCollection();

            ConfigureServices(serviceDescriptors);

            Serilog.Log.Information("Building service provider");

            IServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();

            Console.WriteLine(configuration.GetConnectionString("AppDbConnString"));

            try
            {
                Serilog.Log.Information("start service provider");
                _ = serviceProvider.GetService<App>().Run();
                Serilog.Log.Information("end service provider");
            }
            catch (Exception ex)
            {
                Serilog.Log.Fatal(ex, "Error in building service ");
                throw;
            }
            finally
            {
                Serilog.Log.CloseAndFlush();
            }

            var connectionString = configuration.GetSection("ConnectionStrings:AppDbConnString").Value;

            Console.WriteLine(connectionString);

            var securityGroups = configuration.GetSection("ADSecurityGroups:SupervisorSecurityGroups").Value.Split(';');

            foreach (var securityGroup in securityGroups)
            {
                Console.WriteLine(securityGroup);
            }
        }
        private static void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddSingleton(LoggerFactory.Create(builder =>
            {
                builder.AddSerilog(dispose: true);
            }));

            serviceCollection.AddLogging();

            configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
                .AddJsonFile("appsettings.json")
                .Build();

            serviceCollection.AddSingleton<IConfigurationRoot>(configuration);

            serviceCollection.AddTransient<App>();

        }


    }
}

我的 App.cs 是:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppSettingsExample
{
    public class App
    {
        private readonly IConfigurationRoot _config;
        private readonly ILogger<App> _logger;

        public App(IConfigurationRoot config, ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<App>();
            _config = config;
        }

        public async Task Run()
        {
            List<string> emailAddresses = _config.GetSection("EmailAddresses").Get<List<string>>();
            foreach (string emailAddress in emailAddresses)
            {

                Console.WriteLine(emailAddress);
            }
        }
    }
}

此控制台应用程序的 Output:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM