首页 > 解决方案 > .net core 3:针对不同环境配置DI容器

问题描述

我正在将旧的 .net v 4.5.1 项目移植到最新的 .net 核心。对于旧的 .net 框架项目中的依赖注入,使用 Unity 容器,其中所有服务注册都存储在 web.config 中。

全球.asax:

    UnityConfigurationSection section
        = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
    section.Configure(container, "unityContainer");

网络配置:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container name="primaryUnityContainer">
      <register type="ILogger" mapTo="Log4NetLogger"/>

问题是:.net core 3 在应用程序外部的配置文件中配置服务的最佳方式是什么,例如在 appsettings.json 中,以便可以为不同的环境注册不同的实现。

可以扩展内置容器还是使用具有此功能的某些 3rd 方更好?

为特定环境提供服务实现的其他方法是什么?

标签: .netasp.net-core.net-coredependency-injectionunity-container

解决方案


您不能在应用程序之外的 ASP.NET Core 中配置服务。Microsoft.Extensions.DependencyInjection完全基于代码,虽然您可以使用其他 DI 容器,但它们必须在Microsoft.Extensions.DependencyInjection外观的框架内使用和配置。

也就是说,ASP.NET Core 中的“环境”是基于配置的。您不会为多个不同的环境多次编译应用程序。相反,您可以在启动时通过环境变量ASPNETCORE_ENVIRONMENT(如通过 CLI 参数)或在运行时传递环境来指定环境。

无论哪种情况,您都可以根据环境值在代码中进行分支。实际上,您可以通过三种方式利用环境值来为每个环境配置不同的服务。

  1. 注入IWebHostEnvironment_Startup

    private readonly IWebHostEnvironment _env;
    
    public Startup(IWebHostEnvironment env)
    {
        _env = env;
    }
    

    然后,在ConfigureServices

    if (_env.IsDevelopment())
    {
        ...
    }
    
    if (_env.IsProduction())
    {
        ...
    }
    
    if (_env.IsEnvironment("Foo"))
    {
        ...
    }
    
  2. 使用基于约定的命名与ConfigureServices. 换句话说,你可以Configure{EnvironmentName}Services为你的类定义不同的方法Startup

    public void ConfigureDevelopmentServices(IServiceCollection services)
    {
        ...
    }
    
    public void ConfigureProductionServices(IServiceCollection services)
    {
        ...
    }
    
    public void ConfigureFooServices(IServiceCollection services)
    {
        ...
    }
    
  3. Startup对类本身使用基于约定的命名。您实际上可以定义多个Startup类,如StartupDevelopment, StartupProduction,StartupFoo等。一个问题是,UseStartup<T>当您在Program.cs. 相反,您需要 non-generic UseStartup,它采用程序集名称字符串(因为您不知道在编译时实际需要什么启动类):

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var assemblyName = typeof(Startup).GetTypeInfo().Assembly.FullName;
    
        return WebHost.CreateDefaultBuilder(args)
            .UseStartup(assemblyName);
    }
    

推荐阅读