【发布时间】:2020-02-05 22:24:35
【问题描述】:
我有一个基于 ASP.NET Core 3.1 的应用程序。在应用程序启动期间,我想在ConfigureServices(IServiceCollection services) 中注册我的服务。但是在配置服务的过程中,我想根据数据库中的设置来启动应用程序。
这是我的代码
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 的一个实例。
我的AppSetting 实现依赖于同样注册的AppDbContext。这是我的应用程序设置
public class AppSetting : IAppSetting
{
private AppDbContext context;
public AppSetting(AppDbContext context)
{
this.context = context;
}
// methods...
}
调用BuildServiceProvider() 将导致创建一个额外的单例服务副本。所以我尽量避免这样做。
如何正确注册然后在ConfigureServices() 方法中解析IAppSetting,以便我可以使用它来访问在数据库中找到的设置?
更新
我尝试使用 Nkosi 提供的解决方案,但出现以下错误
System.InvalidOperationException: '无法解析范围服务 来自根提供商的“IAppSetting”。'
这是完整的堆栈跟踪。
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]
【问题讨论】:
-
您不需要
AppSetting来开始机智。改为使用配置系统从数据库加载设置。 -
文档中的 custom configuration provider example 使用 EF Core 从数据库加载设置。您可以轻松地采用它来加载您的设置。
-
至于在 DI 设置阶段访问配置,这是already supported。您可以从传递给 Startup 的
IConfiguration对象中检索所需的配置值
标签: asp.net-core .net-core asp.net-core-mvc asp.net-core-3.0 asp.net-core-3.1