在构建WebHost之前如何访问ASP.NET Core中的服务?

时间:2019-05-26 20:28:14

标签: c# asp.net-core

我们假设我们有以下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的实例;有办法实现吗?

2 个答案:

答案 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)

如评论中所述,如果您的FancyServiceILogger<>没有构造函数依赖性:

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服务已注册为单例,并且一旦创建便从未更改。