【问题标题】:"Microsoft.Extensions.DependencyInjection" and different concretes per environment“Microsoft.Extensions.DependencyInjection”和每个环境的不同具体
【发布时间】:2018-12-03 19:07:10
【问题描述】:

“Microsoft.Extensions.DependencyInjection”

List of "environments"
  Production
  Uat
  Qa
  DevShared
  LocalDev

使用 DotNet (Framework/Classic) 4.6 或更高版本(又名“过去”,我使用带有 xml 配置的“Unity”。https://blogs.msdn.microsoft.com/miah/2009/04/03/testing-your-unity-xml-configuration/

(过去在使用“Unity”IoC/DI 的 Dot Net 核心之前)...当我需要特定于环境的具体内容时,我会调整 .xml 上的具体内容。 例如,假设我的 webApi 需要在生产、uat、qa 和 dev-shared 中进行身份验证。但是在 dev-local 中,我不想在开发 webApi 时一直处理身份验证,我会有 2 个具体的。

IAuthorizer

MyRealAuthorizer : IAuthorizer

MyDevLetEverythingThroughAuthorizer : IAuthorizer

我会“注册”其中一个……使用 xml。

我的构建过程会更改 unity.xml(准确地说是 unity.config)并更改(通过 msbuild 中的 xml-update-tasks)

MyDevLetEverythingThroughAuthorizer

MyRealAuthorizer

.

.....

Java Spring 有基于“注解”的:

import org.springframework.context.annotation.Profile;


@Profile("localdev")
public class MyDevLetEverythingThroughAuthorizer implements IAuthorizer {


@Profile("!localdev")
public class MyRealAuthorizer implements IAuthorizer {

但这不尊重“复合根”模式:(Mark Seeman http://blog.ploeh.dk/2011/07/28/CompositionRoot/)

.......

所以现在我进入了 DotNetCore 的世界。一切都很顺利。但我最终遇到了需要开发友好型混凝土与非开发型“真实”混凝土的情况。

“Microsoft.Extensions.DependencyInjection”无法使用 Xml(据我所知)。

我不确定 DotNetCore 在这种情况下的最佳做法。

我更愿意尊重复合根模式。

基本上,以下……但尊重环境。

asp.net'ish

    public void ConfigureServices(Microsoft.Extensions.DependencyInjection.IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        /* need this for "local-dev" */
        services.AddScoped<IAuthorizer, MyDevLetEverythingThroughAuthorizer>();

        /* need this for everything EXCEPT "local-dev" */
        services.AddScoped<IAuthorizer, MyRealAuthorizer>();

    }

(不是 asp.net)dot.net core'ish too

    private static System.IServiceProvider BuildDi()
    {
        //setup our DI
        IServiceProvider serviceProvider = new ServiceCollection()
            .AddLogging()
            /* need this for "local-dev" */
            .AddSingleton<IAuthorizer, MyDevLetEverythingThroughAuthorizer>()

            /* need this for everything EXCEPT "local-dev" */
            .AddSingleton<IAuthorizer, MyRealAuthorizer>()              

追加

这篇文章和片段帮助我更好地理解“内置内容”部分:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-2.2

环境 ASP.NET Core 读取环境变量 应用程序启动时的 ASPNETCORE_ENVIRONMENT 并将值存储在 IHostingEnvironment.EnvironmentName。你可以设置 ASPNETCORE_ENVIRONMENT 为任何值,但支持三个值 框架:开发、登台和生产。如果 ASPNETCORE_ENVIRONMENT 未设置,默认为生产。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseMvc();
}

env.IsEnvironment("Staging_2") (类似于 env.IsEnvironment("MyCustomValue") )是我猜的技巧。

追加:

这个 SOF 问题让 Asp.Net Core 更清楚了。

How to set aspnetcore_environment in publish file?

以及无需实际设置(机器)环境变量即可设置环境变量的方法!

【问题讨论】:

  • 好的,我去看看。看起来他们有 3 个“预定义”环境,但可以添加自定义环境。 IsDevelopment(IHostingEnvironment) IsProduction(IHostingEnvironment) IsStaging(IHostingEnvironment) IsEnvironment(IHostingEnvironment, String)
  • 我认为您在第三段中的句子“例如,如果我的 webApi ....”中缺少某些内容。你能仔细检查那句话吗?

标签: c# dependency-injection .net-core microsoft.extensions.hosting


【解决方案1】:
public void ConfigureServices(IServiceCollection services, IHostingEnvironment environment) {
        if (environment.IsDevelopment()) {
            // bla bla bla
        } else {
            // bla bla bla
        }
        // register no-matter-which-environment services
}

【讨论】:

  • 因为IHostingEnvironment 也存在于Configure 方法中,如果您使用此方法,我建议从控制器注入它。这样你只需要在一个地方注入它
  • 他想在启动时注册一些类型。在控制器中注入它如何帮助他?
  • 我的意思是 *constructor (of the startup) 错字,我的错
  • 可以使用。我同意
【解决方案2】:

您的问题似乎在谈论两件事:从 XML 文件设置配置和使用 IServiceCollection 管理服务。对于 .net 核心网络应用程序,这些发生在两个阶段:

  1. 从各种预定义和自定义源(包括 json、XML、环境)合并键值对。所有预设的 .net 核心 Web 模板都在 program.cs 中执行此操作。

  2. 键值对集合被发送到Startup 类,该类可以通过 DI 从IConfiguration 变量访问。检查this link 了解更多信息。

在这个过程中,所有配置文件都在ConfigureServices 方法在Startup 类中被调用之前添加。如果您想在此配置中添加 XML 文件,可以在您的 program.cs 中设置以下代码:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    // additional code
        .UseConfiguration(
            new ConfigurationBuilder()
            .AddXmlFile("file.xml", true) // second param is if file is optional
            .Build()
        )
    // end of additional code
        .UseStartup<Startup>();

如果您想访问您的环境,如果它们被设置为环境变量,您可以使用Environment.Get... 函数之一。

关于您的服务,我不确定您尝试以何种方式访问​​您的 XML,但如果您需要,您始终可以注入 IConfiguration 作为最简单的解决方案。但是,我建议不要将您的整个配置暴露给您的服务,并在 this documentation 的帮助下查看设置选项

【讨论】:

  • 感谢您的意见。但是,我在原始问题中确实声明了“我将“Unity”与 xml 配置一起使用。” Aka,当我使用 Unity IoC/DI 时,xml 部分是“过去的”。它只是定义了我过去如何使用 Dotnet-Framework(不是 Core)。我将编辑我的问题文本以强调这一点。
  • 我已经看到了这一点并刷过链接。基本上,我在 .NET Framework 中看到和使用的所有内容(如 web.config)都以这两种方式处理其所有功能。换句话说,这些 xmls 过去提供的功能通常分为添加服务和IConfiguration 功能。您通常需要具体了解您在 DI 中试图实现的目标,并检查如何将它们转化为这两个
  • 基本上你只需要MyDevLetEverythingThroughAuthorizer应该用于开发环境,MyRealAuthorizer必须是IAuthorizer的定义?
  • 回答“基本上”的问题............是的。但请记住,我有两个“开发”环境。 “devlocal”(又名“我的机器”)......和“devshared”(又名,开发人员将运行的代码放在哪里......不在“我的机器”中)。它的分裂头发,但只是强调这一点。
猜你喜欢
  • 1970-01-01
  • 2018-09-01
  • 2020-11-29
  • 1970-01-01
  • 2021-12-14
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多