如何在 .NET Core 控制台应用程序中设置 DI 容器?

5 c# .net-core

我创建了一个新的 .NET Core 控制台应用程序并安装了以下软件包

  • Microsoft.扩展.配置
  • Microsoft.Extensions.Configuration.EnvironmentVariables
  • Microsoft.Extensions.Configuration.Json
  • Microsoft.Extensions.DependencyInjection
  • Microsoft.扩展.选项
  • Microsoft.Extensions.Options.ConfigurationExtensions

我为配置创建了一个 appsettings.json 文件

{
  "app": {
    "foo": "bar" 
  }
}
Run Code Online (Sandbox Code Playgroud)

我想将这些值映射到一个类

internal class AppOptions
{
    public string Foo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我还想在配置过程中验证选项,因此我添加了一个验证类

internal class AppOptionsValidator : IValidateOptions<AppOptions>
{
    public ValidateOptionsResult Validate(string name, AppOptions options)
    {
        IList<string> validationFailures = new List<string>();

        if (string.IsNullOrEmpty(options.Foo))
            validationFailures.Add("Foo is required.");

        return validationFailures.Any()
        ? ValidateOptionsResult.Fail(validationFailures)
        : ValidateOptionsResult.Success;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想设置 DI 容器并创建一个测试场景

    static void Main(string[] args)
    {
        ConfigureServices();

        Console.ReadLine();
    }

    private static void ConfigureServices()
    {
        IServiceCollection serviceCollection = new ServiceCollection();
        IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();

        // Setup configuration service

        IConfiguration configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .AddEnvironmentVariables()
            .Build();

        serviceCollection.AddSingleton(configuration);

        // Setup options

        IConfiguration configurationFromDI = serviceProvider.GetService<IConfiguration>(); // This is just for testing purposes

        IConfigurationSection myConfigurationSection = configurationFromDI.GetSection("app");

        serviceCollection.AddSingleton<IValidateOptions<AppOptions>, AppOptionsValidator>();
        serviceCollection.Configure<AppOptions>(myConfigurationSection);

        // Try to read the current options

        IOptions<AppOptions> appOptions = serviceProvider.GetService<IOptions<AppOptions>>();

        Console.WriteLine(appOptions.Value.Foo);
    }
Run Code Online (Sandbox Code Playgroud)

不幸的是该变量configurationFromDI为空。因此该变量configuration没有添加到 DI 容器中。

如何正确设置控制台应用程序的依赖注入?

Pan*_*vos 6

应在所有服务注册BuildServiceProvider进行调用。

不过,没有必要编写所有这些代码。由于您已经使用了如此多的扩展,因此最好(也更容易)使用通用 Host,就像 ASP.NET Core 应用程序使用其ConfigureServices,ConfigureAppConfiguration方法一样:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureHostConfiguration(configuration =>
            {
                configuration....;
            });
            .ConfigureServices((hostContext, services) =>
            {
                var myConfigurationSection = configuration.GetSection("app");

                services.AddSingleton<IValidateOptions<AppOptions>, AppOptionsValidator>();
                services.Configure<AppOptions>(myConfigurationSection);

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

可通过HostBuilderContext.Configuration属性进行配置。

CreateDefaultBuilder设置当前文件夹、配置环境变量和文件的使用appsettings.json,因此无需显式添加它们。

Appsettings.json 复制设置

在 Web 应用程序模板中,appsettings.json文件会自动添加,Build Action属性设置为ContentCopy to Output操作设置为Copy if Newer

控制台应用程序中没有此类文件。appsettings.json当手动添加新文件时,其Build ActionisNoneCopyto Never。调试应用程序时,当前目录为bin\Debug. 使用默认设置,appsettings.json不会被复制到bin/Debug

Build Action必须更改为ContentCopy应设置为Copy if NewerCopy Always