如何在没有 BuildServiceProvider 的情况下直接从 ConfigureServices 访问 Singleton?
How to access Singleton directly from ConfigureServices without BuildServiceProvider?
如何从ConfigureServices
访问单例?有几个配置我不能使用 appsettings
是有原因的。
例如,假设我想从数据库设置swagger标题和版本,而不是appsettings
。我的实际问题是我想从我的数据库中设置领事地址。问题应该是一样的,我需要在 ConfigureServices 中访问我的数据库。我有一个这样的自定义扩展:
public static IServiceCollection AddConsulConfig(this IServiceCollection services, string address)
{
services.AddSingleton<IConsulClient, ConsulClient>(p => new ConsulClient(consulConfig =>
{
consulConfig.Address = new Uri(address);
}));
return services;
}
我从启动时调用它:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IGlobalParameter, GlobalParameterManager>();
//I want to use IGlobalParameter here directly but without BuildServiceProvider
//This part is the problem
var service = ??
var varTitle = service.GetById("Title").Result.Value;
var varConsulAddress = service.GetById("ConsulAddress").Result.Value;
services.AddConsulConfig(varConsulAddress);
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = varTitle, Version = "v1" });
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// I can use it here or in the controller no problem
var service = app.ApplicationServices.GetRequiredService<IGlobalParameter>();
var varTitle = service.GetById("Title").Result.Value;
var varConsulAddress = service.GetById("ConsulAddress").Result.Value;
}
我不想使用BuildServiceProvider,因为它会产生多个实例,甚至visual studio也会给出警告。在
中引用
我从下面的 link 知道 IConfigureOptions 的存在
https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/#the-new-improved-answer
但是,我似乎无法在 ConfigureService
:
中找到确切的使用方法
public class ConsulOptions : IConfigureOptions<IServiceCollection>
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public ConsulOptions(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public void Configure(IServiceCollection services)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var provider = scope.ServiceProvider;
IGlobalParameter globalParameter = provider.GetRequiredService<IGlobalParameter>();
var ConsulAddress = globalParameter.GetById("ConsulAddress").Result.Value;
services.AddConsulConfig(ConsulAddress);
}
}
}
启动时设置:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IGlobalParameter, GlobalParameterManager>();
services.AddSingleton<IConfigureOptions<IServiceCollection>, ConsulOptions>(); // So what? it's not called
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// IConsulClient is still null here
}
有什么方法可以解决这个问题?
谢谢 Jeremy,就这么简单。我不知道为什么我花了太多时间弄清楚如何设置它
解决方法是添加单例:
services.AddSingleton<IConsulClient, ConsulClient>(
p => new ConsulClient(consulConfig =>
{
var ConsulAddress = p.GetRequiredService<IGlobalParameter>().GetById("ConsulAddress").Result.Value;
consulConfig.Address = new Uri(ConsulAddress);
}
));
如何从ConfigureServices
访问单例?有几个配置我不能使用 appsettings
是有原因的。
例如,假设我想从数据库设置swagger标题和版本,而不是appsettings
。我的实际问题是我想从我的数据库中设置领事地址。问题应该是一样的,我需要在 ConfigureServices 中访问我的数据库。我有一个这样的自定义扩展:
public static IServiceCollection AddConsulConfig(this IServiceCollection services, string address)
{
services.AddSingleton<IConsulClient, ConsulClient>(p => new ConsulClient(consulConfig =>
{
consulConfig.Address = new Uri(address);
}));
return services;
}
我从启动时调用它:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IGlobalParameter, GlobalParameterManager>();
//I want to use IGlobalParameter here directly but without BuildServiceProvider
//This part is the problem
var service = ??
var varTitle = service.GetById("Title").Result.Value;
var varConsulAddress = service.GetById("ConsulAddress").Result.Value;
services.AddConsulConfig(varConsulAddress);
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = varTitle, Version = "v1" });
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// I can use it here or in the controller no problem
var service = app.ApplicationServices.GetRequiredService<IGlobalParameter>();
var varTitle = service.GetById("Title").Result.Value;
var varConsulAddress = service.GetById("ConsulAddress").Result.Value;
}
我不想使用BuildServiceProvider,因为它会产生多个实例,甚至visual studio也会给出警告。在
我从下面的 link 知道 IConfigureOptions 的存在 https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/#the-new-improved-answer
但是,我似乎无法在 ConfigureService
:
public class ConsulOptions : IConfigureOptions<IServiceCollection>
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public ConsulOptions(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public void Configure(IServiceCollection services)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var provider = scope.ServiceProvider;
IGlobalParameter globalParameter = provider.GetRequiredService<IGlobalParameter>();
var ConsulAddress = globalParameter.GetById("ConsulAddress").Result.Value;
services.AddConsulConfig(ConsulAddress);
}
}
}
启动时设置:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IGlobalParameter, GlobalParameterManager>();
services.AddSingleton<IConfigureOptions<IServiceCollection>, ConsulOptions>(); // So what? it's not called
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// IConsulClient is still null here
}
有什么方法可以解决这个问题?
谢谢 Jeremy,就这么简单。我不知道为什么我花了太多时间弄清楚如何设置它
解决方法是添加单例:
services.AddSingleton<IConsulClient, ConsulClient>(
p => new ConsulClient(consulConfig =>
{
var ConsulAddress = p.GetRequiredService<IGlobalParameter>().GetById("ConsulAddress").Result.Value;
consulConfig.Address = new Uri(ConsulAddress);
}
));