如何正确解析服务以在 ASP.NET Core 3.1 的 ConfigureServices() 中使用? [英] How to correctly resolve services to use in the ConfigureServices() in ASP.NET Core 3.1?

查看:19
本文介绍了如何正确解析服务以在 ASP.NET Core 3.1 的 ConfigureServices() 中使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于 ASP.NET Core 3.1 的应用程序.在应用程序启动期间,在 ConfigureServices(IServiceCollection services) 中,我想注册我的服务.但是在配置服务时,我想根据数据库中的设置启动应用程序.

I have an ASP.NET Core 3.1 based app. During the app startup, in the ConfigureServices(IServiceCollection services) I want to register my services. But during configuring services, I want to boot the app based on settings found in the database.

这是我的代码

public void ConfigureServices(IServiceCollection services)
{
    // Register context
    services.AddDbContext<AppDbContext>(options =>
    {
        options.UseMySql(Configuration.GetConnectionString("MySqlServerConnection"));
    });

    // Reister the setting provider
    services.AddSingleton<IAppSetting, AppSettings>();

    // Create a resolver which is WRONG!!
    var resolver = services.BuildServiceProvider();

    var setting = resolver.GetService<IAppSetting>();

    List<string> allowedCors = new List<string>()
    {
         setting.MainUrl.ToString()
    };

    if (setting.HasCustomAssetsUri)
    {
        allowedCors.Add(settings.AssetsUrl.ToString());
    }

    if (settings.HasCustomPhotosUri)
    {
        allowedCors.Add(settings.PhotosUrl.ToString());
    }

    services.AddCors(options =>
    {
        options.AddPolicy("AllowSubDomainTraffic",
        builder =>
        {
            builder.WithOrigins(allowedCors.ToArray())
                   .AllowAnyHeader()
                   .AllowAnyMethod();
        });
    });

    // More services
}

正如您在上面的代码中看到的,我注册了 IAppSetting 但我立即想使用它来访问数据库,以便获取当前配置.我目前正在调用 services.BuildServiceProvider() 来创建一个新的解析器,然后我可以在其中使用它来创建 IAppSetting 的实例.

As you can see in the above code, I register the IAppSetting but I immediately want to use to access the database so get the current configuration. I am currently calling services.BuildServiceProvider() to create a new resolver in which I can then use it to create an instance of the IAppSetting.

我的 AppSetting 实现依赖于同样注册的 AppDbContext.这是我的 AppSetting

My AppSetting implementation depends on the AppDbContext which is also registered. Here is my AppSetting

public class AppSetting : IAppSetting
{
    private AppDbContext context;

    public AppSetting(AppDbContext context)
    {
        this.context = context;
    }

    // methods...
}

调用 BuildServiceProvider() 将导致创建单例服务的额外副本.所以我尽量避免这样做.

Calling BuildServiceProvider() will result in an additional copy of singleton services being created. so I am trying to avoid having to do this.

如何正确注册并解析 ConfigureServices() 方法中的 IAppSetting,以便我可以使用它来访问在数据库中找到的设置?

How can I correctly register and then resolve IAppSetting in the ConfigureServices() method so I can use it to access the settings found in the database?

更新

我尝试使用 Nkosi 提供的解决方案,但出现以下错误

I attempted to use the solution presented by Nkosi, but getting the following error

System.InvalidOperationException: '无法解析范围服务来自根提供程序的IAppSetting".'

System.InvalidOperationException: 'Cannot resolve scoped service 'IAppSetting' from root provider.'

这是完整的堆栈跟踪.

This exception was originally thrown at this call stack:
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(System.Type, Microsoft.Extensions.DependencyInjection.IServiceScope, Microsoft.Extensions.DependencyInjection.IServiceScope)
    Microsoft.Extensions.DependencyInjection.ServiceProvider.Microsoft.Extensions.DependencyInjection.ServiceLookup.IServiceProviderEngineCallback.OnResolve(System.Type, Microsoft.Extensions.DependencyInjection.IServiceScope)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(System.Type)
    Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(System.IServiceProvider, System.Type)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(Microsoft.Extensions.DependencyInjection.ServiceLookup.FactoryCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite, Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext)
    ...
    [Call Stack Truncated]

推荐答案

参考 使用DI服务配置选项

使用 DI 配置 CORS 选项,将所有逻辑移动到配置委托中

Configure the CORS options using DI, moving all the logic into the configure delegate

//...

// Register context
services.AddDbContext<AppDbContext>(options => {
    options.UseMySql(Configuration.GetConnectionString("MySqlServerConnection"));
});

// Reister the setting provider
services.AddScoped<IAppSetting, AppSettings>(); 

//configure CORS options using DI
services.AddOptions<CorsOptions>()
    .Configure<IServiceScopeFactory>((options, sp) => {
        using(var scope = sp.CreateScope()) {
            IAppSetting settings = scope.ServiceProvider.GetRequiredService<IAppSetting>();
            List<string> allowedCors = new List<string>() {
                 setting.MainUrl.ToString()
            };

            if (setting.HasCustomAssetsUri) {
                allowedCors.Add(settings.AssetsUrl.ToString());
            }

            if (settings.HasCustomPhotosUri) {
                allowedCors.Add(settings.PhotosUrl.ToString());
            }
            options.AddPolicy("AllowSubDomainTraffic", builder => {
                builder.WithOrigins(allowedCors.ToArray())
                       .AllowAnyHeader()
                       .AllowAnyMethod();
            });
        }
    });

services.AddCors();

//...

这样,现在一切都被推迟到真正需要的时候,您就可以避免过早地构建服务集合.

that way everything is now deferred to when they are actually needed and you avoid having to build the service collection prematurely.

这篇关于如何正确解析服务以在 ASP.NET Core 3.1 的 ConfigureServices() 中使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆