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

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

问题描述

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

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.

这是我的代码

Here is my code

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.

如何正确注册然后解析 IAppSetting ConfigureServices()方法,以便可以使用它访问数据库中的设置吗?

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天全站免登陆