从ASP.NET Core 2.2迁移到3.1时,services.BuildServiceProvider(在ConfigureServices中)的备用代码

时间:2019-12-13 05:50:21

标签: asp.net asp.net-core .net-core asp.net-core-3.0 .net-core-3.0

我有模块化的ASP.NET Core应用程序。回到.NET Core 1.1的日子,我以AddScoped方法构建服务(AddSingletonpublic void ConfigureServices(IServiceCollection services) ...),如下所示:

public void ConfigureServices(IServiceCollection services)
{
    //...
    var sp = services.BuildServiceProvider();
    GlobalConfiguration.ModuleInitializers = sp.GetServices<IModuleInitializer>();
    foreach (var moduleInitializer in GlobalConfiguration.ModuleInitializers)
        moduleInitializer.ConfigureServices(services, this.Configuration, this.Environment);
}

每个模块(库)都有自己的类,该类实现“ IModuleInitializer”并注册服务:

public class ModuleInitializer : IModuleInitializer
{
    public void ConfigureServices(IServiceCollection serviceCollection, IConfiguration configuration, IHostingEnvironment environment)
    {
        serviceCollection.AddScoped<....>();
        serviceCollection.AddScoped<...>();
        ...

从.NET Core 2.2迁移到3.1时,我收到警告:

  

从应用程序代码中调用“ BuildServiceProvider”会导致   正在创建的单例服务的其他副本。考虑   诸如依赖项注入服务之类的替代方案   '配置'

我已经接受了自我教育,这意味着什么,问题出在哪里……,但是我在如何在模块设计应用程序中正确配置服务方面遇到了问题。

我还需要从Internet获得有关模块的信息。我的问题是这种方法是否有效,还是有更好的建议?

public Startup(IConfiguration configuration)
{
    Configuration = configuration;    //From https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-3.1
}

public void ConfigureServices(IServiceCollection services)
{
    ...

    var serverSett = this.Configuration.GetSection("Server").Get<ServerSettings>();
    string[] allowedModules;
    using (var httpClientHandler = new HttpClientHandler())
    {
        allowedModules = //Get allowed modules from web
    }
    if (allowedModules.Any(t => t == "Shopping");
        services.AddShopping();    //Extension method in Shopping library which register own services.
    if (allowedModules.Any(t => t == "Offer");
        services.AddOffer();    //Extension method in Offer library which register own services.
}

1 个答案:

答案 0 :(得分:0)

使用DI设置DI有点问题,而且肯定有问题。

为什么不仅仅使用一些反射来获取IModuleInitializers。

var moduleInitializers = typeof(MyAssembly).GetTypeInfo().Assembly
    .GetTypes()
    .Where(type =>
        !type.GetTypeInfo().IsAbstract &&
        typeof(IModuleInitializer).IsAssignableFrom(type))
    .Select(type => Activator.CreateInstance(type))
    .Cast<IModuleInitializer>()
    .ToArray();

foreach (var moduleInitializer in moduleInitializers)
    moduleInitializer.ConfigureServices(services, this.Configuration, this.Environment);

关于第二个问题,我无法给您建议。但是我会质疑是否需要动态设置应用程序,除非您真的很需要。