【问题标题】:.net core 3: configure DI container for different environments.net core 3:针对不同环境配置DI容器
【发布时间】:2020-04-24 01:49:22
【问题描述】:

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

全球.asax:

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

web.config:

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

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

可以扩展内置容器还是最好使用具有此功能的第三方?

还有哪些其他方法可以针对特定环境进行服务实现?

【问题讨论】:

    标签: .net asp.net-core .net-core dependency-injection unity-container


    【解决方案1】:

    您不能在应用程序之外的 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 使用基于约定的命名。换句话说,您可以为您的Startup 类定义不同的Configure{EnvironmentName}Services 方法:

      public void ConfigureDevelopmentServices(IServiceCollection services)
      {
          ...
      }
      
      public void ConfigureProductionServices(IServiceCollection services)
      {
          ...
      }
      
      public void ConfigureFooServices(IServiceCollection services)
      {
          ...
      }
      
    3. Startup 类本身使用基于约定的命名。您实际上可以定义多个Startup 类,例如StartupDevelopmentStartupProductionStartupFoo 等。一个问题是,在Program.cs 中设置主机时,您不能再使用通用UseStartup&lt;T&gt; 方法.相反,您需要非泛型 UseStartup,它采用程序集名称字符串(因为在编译时您不知道实际需要什么启动类):

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

    【讨论】:

      【解决方案2】:

      你下面的配置设置类型:

      public Startup(IHostingEnvironment env)
      {
          var builder = new ConfigurationBuilder()
          .SetBasePath(env.ContentRootPath)
          .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
      #if SOME_BUILD_FLAG_A
          .AddJsonFile($"appsettings.flag_a.json", optional: true)
      #else
          .AddJsonFile($"appsettings.no_flag_a.json", optional: true)
      #endif
          .AddEnvironmentVariables();
          this.configuration = builder.Build();
      }
      

      【讨论】:

      • 不要对这样的事情使用编译器指令。这太可怕了,而且是错误的。
      猜你喜欢
      • 2018-10-26
      • 2019-02-14
      • 2017-03-13
      • 2018-02-12
      • 2018-04-01
      • 2020-09-20
      • 2019-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多