Configure DI container for different environments in .NET Core 3.

huangapple go评论69阅读模式
英文:

.net core 3: configure DI container for different environments

问题

在将旧的.NET Framework 4.5.1项目迁移到最新的.NET Core时,依赖注入在旧的.NET Framework项目中使用Unity容器进行,其中所有服务注册都存储在web.config中。

Global.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,以便不同的实现可以为不同的环境进行注册。

内置容器是否可以扩展,或者最好使用一些具有此功能的第三方容器?

还有哪些其他方法可以为特定环境提供服务实现?

英文:

I'm porting old .net v 4.5.1 project to the latest .net core.
For dependency injection in old .net framework project Unity container is used where all service registrations are stored in web.config.

Global.asax:

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

web.config:

&lt;unity xmlns=&quot;http://schemas.microsoft.com/practices/2010/unity&quot;&gt;
&lt;container name=&quot;primaryUnityContainer&quot;&gt;
      &lt;register type=&quot;ILogger&quot; mapTo=&quot;Log4NetLogger&quot;/&gt;

The questing is: what are the best way in .net core 3 to configure the services in a configuration file outside the application, in appsettings.json for example so that different implementations could be registered for different environments.

Can built-in container be extended or it's better to use some 3rd party with this feature?

What are other approaches to have service implementations for specific environment?

答案1

得分: 3

以下是您要翻译的内容:

你不能在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<T> 方法。而需要使用非泛型的 UseStartup 方法,它接受一个程序集名称字符串(因为你在编译时不知道实际需要的启动类):

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

You cannot configure services in ASP.NET Core outside of the application. Microsoft.Extensions.DependencyInjection is entirely code-based, and while you can use other DI containers, they must be used and configured within the framework of the Microsoft.Extensions.DependencyInjection facade.

That said, "environments" in ASP.NET Core are config-based. You don't compile the application multiple times for multiple different environments. Instead the you specify the environment on startup via either an environment variable like ASPNETCORE_ENVIRONMENT or passing the environment at runtime such as via an CLI argument.

In either case, you can then branch in your code based on the environment value. There's actually three ways you can utilize the environment value to configure services differently per environment.

  1. Inject IWebHostEnvironment into Startup

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

Then, in ConfigureServices:

    if (_env.IsDevelopment())
    {
        ...
    }

    if (_env.IsProduction())
    {
        ...
    }

    if (_env.IsEnvironment(&quot;Foo&quot;))
    {
        ...
    }
  1. Use conventions-based naming with ConfigureServices. In other words, you can define different Configure{EnvironmentName}Services methods to your Startup class:

     public void ConfigureDevelopmentServices(IServiceCollection services)
     {
         ...
     }
    
     public void ConfigureProductionServices(IServiceCollection services)
     {
         ...
     }
    
     public void ConfigureFooServices(IServiceCollection services)
     {
         ...
     }
    
  2. Use conventions-based naming with the Startup class itself. You can actually define multiple Startup classes like StartupDevelopment, StartupProduction, StartupFoo, etc. The one catch is that you can then no longer use the generic UseStartup&lt;T&gt; method when setting up your host in Program.cs. Instead, you need the non-generic UseStartup, which takes an assembly name string (as you won't know what startup class you actually need at compile-time):

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

答案2

得分: -1

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();
}

英文:

you below type of configuration setting :

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

huangapple
  • 本文由 发表于 2020年1月6日 21:59:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/59613442.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定