如何从 Startup.cs 中的 Configure 方法调用 services.Configure

Posted

技术标签:

【中文标题】如何从 Startup.cs 中的 Configure 方法调用 services.Configure【英文标题】:How to call services.Configure from Configure method in Startup.cs 【发布时间】:2020-04-25 23:01:00 【问题描述】:

在我的 Startup.cs 文件中的 ConfigureServices() 中,我称之为

if (services.BuildServiceProvider().GetService<IWebHostEnvironment>().IsDevelopment()) 
 services.Configure<EnvironmentSettings>(Configuration.GetSection("WebServicesDevelopment"));
 else 
 services.Configure<EnvironmentSettings>(Configuration.GetSection("WebServicesProduction"));

我收到一个构建警告说

从应用程序代码中调用“BuildServiceProvider”会导致创建一个额外的单例服务副本。考虑将依赖注入服务等替代方案作为“配置”的参数

如何使用 IApplicationBuilder 从 Configure() 调用它?

【问题讨论】:

为什么要移动它?这两种方法用于执行两个单独的任务。您在 ConfigureServices 中配置服务,在 Configure 中配置应用程序管道 因为当我构建时,我收到一条警告说“从应用程序代码调用'BuildServiceProvider'会导致创建一个额外的单例服务副本。考虑将依赖注入服务等替代方案作为“配置”的参数'" 对不起!让我编辑我的帖子以进一步解释。 哦,我想我可以将“IServiceCollection”注入“Configure()”? 不,不要那样做。看我的回答 【参考方案1】:

首先,检查multiple environments support in ASP.NET Core。您可以配置环境特定部分以避免代码中的if-else 语句。

现在假设上述方法不适合你:

您应避免按照警告消息中所述的原因在ConfigureServices 方法中构建容器。

相反,您应该使用options pattern:

services.AddOptions<EnvironmentSettings>()
    .Configure<IConfiguration, IWebHostEnvironment>(
        (settings, config, env) =>
        
            if (env.IsDevelopment())
            
                config.GetSection("WebServicesDevelopment").Bind(settings);
            
            else
            
                config.GetSection("WebServicesProduction").Bind(settings);
            
        );

【讨论】:

【参考方案2】:

正如警告所述,调用BuildServiceProvider 可能会产生意想不到的副作用,并且是一种反模式。服务是在ConfigureServices 中配置的,我们拥有所有必要的工具来根据环境执行条件配置。只需在 Startup 类的构造函数中注入 IWebHostEnvironment 并适当地配置您的服务:

public class Startup

    private readonly IWebHostEnvironment _env;

    public Startup(IConfiguration configuration, IWebHostEnvironment env /* take dependency on environment */)
    
        Configuration = configuration;
        _env = env; // store environment
    

    public IConfiguration Configuration  get; 

    public void ConfigureServices(IServiceCollection services)
    
        // configure based on environment
        if (_env.IsDevelopment())
         
            services.Configure<EnvironmentSettings>(Configuration.GetSection("WebServicesDevelopment"));
         
        else 
        
           // non-dev services
           services.Configure<EnvironmentSettings>(Configuration.GetSection("WebServicesProduction"));
        
    

请参阅以下文档:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-3.1 搜索短语“只能注入以下服务类型”

This link 有更多信息,包括如何拥有多个 Startup 类或多个 ConfigureServices 方法(每个环境)

【讨论】:

嗨粉红色。我认为我必须解决的问题是,在您的 if 语句中,在您检查开发环境的地方,我需要运行此“services.Configure(Configuration.GetSection("WebServicesDevelopment"));”它使用从 appsettings 文件中提取的所有适当数据填充 EnvironmentSettings 对象。我需要弄清楚如何在配置方法中做到这一点。或者相反,确定 ConfigureServices 方法中的 dev/prod 是否可以工作! 不,您不需要在 Configure 中执行此操作。您需要/必须在 ConfigureServices 中执行此操作。我的示例准确显示了如何确定 ConfigureServices 中的 dev/prod 是否存在。我没有关注你的担忧。在上面代码中的“// Dev services”后面加上services.Configure&lt;EnvironmentSettings&gt;(Configuration.GetSection("WebServicesDevelopment")),在else块中添加另一个版本

以上是关于如何从 Startup.cs 中的 Configure 方法调用 services.Configure的主要内容,如果未能解决你的问题,请参考以下文章

如何更新 startup.cs 中的服务顶部使用 ITableEntity 和 TableClient 作为 dotnet3.1 中的服务

从 startup.cs 检查令牌有效性

如何在 .NET 5 隔离进程中使用 Azure Functions v3 时添加以前在 Startup.cs 中的代码->配置方法

在 Startup.cs 中初始化 Blob 存储

ASP .NET MVC 5 中使用的 Startup.Auth.cs 和 Startup.cs 是啥?

无法访问 MVC 6 API