我们假设我们有以下Program.cs
:
public static class Program
{
public static async Task Main(string[] args)
{
await CreateWebHostBuilder(args).Build().RunAsync();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost
.CreateDefaultBuilder(args)
.ConfigureKestrel(options => { options.AllowSynchronousIO = false; })
.ConfigureFanciness()
.ConfigureLogging(ConfigureApplicationLogging)
.UseStartup<Startup>();
}
private static void ConfigureApplicationLogging(WebHostBuilderContext context, ILoggingBuilder loggingBuilder)
{
var loggingConfiguration = context.Configuration.GetSection("Logging");
loggingBuilder.AddConfiguration(loggingConfiguration);
// var fancyService = SomehowGet<IFancyService>();
// if (fancyService.IsEnabled)
// loggingBuilder.AddEventLog(loggingConfiguration);
}
public static IWebHostBuilder ConfigureFanciness(this IWebHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices(delegate (WebHostBuilderContext context, IServiceCollection services)
{
var fancinessConfiguration = context.Configuration.GetSection("Fanciness");
services.Configure<FancinessSettings>(fancinessConfiguration);
services.AddSingleton<IFancyService, FancyService>();
// var fancyService = SomehowGet<IFancyService>();
// fancyService.Initialize();
});
}
}
以及以下FancyService.cs
:
public sealed class FancyService : IFancyService
{
private readonly ILogger<FancyService> logger;
private readonly IOptions<FancinessSettings> settings;
public FancyService(ILogger<FancyService> logger, IOptions<FancinessSettings> settings)
{
this.logger = logger;
this.settings = settings;
}
public bool IsEnabled { get; private set; }
public void Initialize()
{
// do the initialization work and set IsEnabled to some value
}
}
如示例文件所示,loggingBuilder.AddEventLog(loggingConfiguration)
取决于调用IFancyService.IsEnabled
时设置的IFancyService.Initialize()
。
为此,我需要访问IFancyService
的实例;有办法实现吗?
答案 0 :(得分:0)
一旦调用services.AddSingleton<IFancyService, FancyService>()
,您就可以通过构建FancyService
来获取ServiceProvider
的实例:
private static void ConfigureApplicationLogging(WebHostBuilderContext context, ILoggingBuilder loggingBuilder)
{
var fancyService = loggingBuilder.Services.BuildServiceProvider().GetService<IFancyService>();
fancyService.Initialize();
var loggingConfiguration = context.Configuration.GetSection("Logging");
loggingBuilder.AddConfiguration(loggingConfiguration);
if (fancyService.IsEnabled)
loggingBuilder.AddEventLog(loggingConfiguration);
}
答案 1 :(得分:0)
如评论中所述,如果您的FancyService
对ILogger<>
没有构造函数依赖性:
public sealed class FancyService : IFancyService
{
public FancyService(IOptions<FancinessSettings> settings)
{ ... }
要初始化IFancyService
,只需使用实现工厂创建一个IFancyService
实例:
public static IWebHostBuilder ConfigureFanciness(this IWebHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices(delegate (WebHostBuilderContext context, IServiceCollection services)
{
var fancinessConfiguration = context.Configuration.GetSection("Fanciness");
services.Configure<FancinessSettings>(fancinessConfiguration);
services.AddSingleton<IFancyService, FancyService>(sp =>{
var fancy=ActivatorUtilities.CreateInstance(sp,typeof(FancyService)) as FancyService;
fancy.Initialize();
return fancy;
});
});
}
相同的技巧也可以用于注册记录器提供程序。由于ILogger<>
服务取决于IEnumberable<ILoggerProvider>
,因此我们可以注册一个ILoggerProvider
实例,该实例提供一个额外的INullLogger
以便根据当前{{1} }:
IFancyService
请注意,构建记录器后,请勿更改private static void ConfigureApplicationLogging(WebHostBuilderContext context, ILoggingBuilder loggingBuilder)
{
var loggingConfiguration = context.Configuration.GetSection("Logging");
var descriptor=ServiceDescriptor.Singleton<ILoggerProvider,NullLoggerProvider>(sp =>{
var provider = NullLoggerProvider.Instance;
var fancy = sp.GetRequiredService<IFancyService>();
if(fancy.IsEnabled)
{
loggingBuilder.AddDebug();
loggingBuilder.AddEventLog(loggingConfiguration);
loggingBuilder.AddEventSourceLogger();
// ... add more configuration as you like
}else{
loggingBuilder.AddConsole();
}
return provider;
});
loggingBuilder.Services.TryAddEnumerable(descriptor);
loggingBuilder.AddConfiguration(loggingConfiguration);
}
。这是因为IFancyService.IsEnabled
服务已注册为单例,并且一旦创建便从未更改。