问题描述
我有一个基于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 $的实例。 c $ c>。
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
这是完整的堆栈跟踪。
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配置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()中使用的服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!