Net Core: ILogger in Startup Class: Encapsulate in Extension Method

Net Core: ILogger in Startup Class: Encapsulate in Extension Method

我在Net Core中写了这段日志代码,有人提到“这可以封装在扩展方法中”。这是执行此操作的更简单方法吗,在 Net Core 2.2 中以最佳方式编写它?

Startup.cs

services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddLogging(builder => builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace));

好吧,可以按照AddLogging编写扩展方法的方式来完成。

public static IServiceCollection AddCustomLogging (this IServiceCollection services) {  
    services.AddSingleton<ILoggerFactory, LoggerFactory>();
    services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
    services.AddLogging(builder => builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace)); 
}

虽然这不可能是一个纯粹的 Whosebug 问题,但我想我可以提供一个意见:

方法 ConfigureServices 的问题是您需要定义所有依赖项,对于较大的系统,这可能意味着痛苦的长配置方法,维护起来真的很难和无聊。

要解决此问题,您可以通过划分所有配置来简化启动,为此,您可以使用 C# 的 extension methods,该方法允许 "extend" a class(添加更多方法)无需修改class.

的源代码

扩展方法很简单,就拿一个静态的class用一个静态的方法:

public static class CommonServicesExtension
{

    public static IServiceCollection AddCommonServices(IServiceCollection services)
    {
        services.AddHttpClient();
        services.AddNodaDateTime();
        services.AddMemoryCache();
        services.AddCurrencyExchange();
        // Add and configure many things

        return services;
    }
}

现在你可以这样使用了:

CommonServicesExtension.AddCommonServices(serviceColletion);

但这有点丑陋且难以阅读,因此,只需将 this 添加到您的扩展方法中即可:

public static IServiceCollection AddCommonServices(this IServiceCollection services)

通过此更改,您可以像 net core 一样调用您的配置!

services.AddCommonServices();

在你的配置服务中,这样,你的配置方法从

public IServiceCollection ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();

    services.AddDbContext<CoreContext>(options => options.UseMySql(Configuration.GetConnectionString("Core")));
    services.AddDbContext<CoreReadOnlyContext>(options => options.UseMySql(Configuration.GetConnectionString("CORE_READONLY")));
    services.AddDbContext<StatsContext>(options =>
        options.UseMySql(Configuration.GetConnectionString("Stats")));


    services.AddScoped<ProfileTokenGenerator>();
    services.AddTransient<MailNotificationService>();
    services.AddTransient<RegisterControllerService>();

    services.AddScoped<OtherClass>();
    services.AddTransient<MoreTransient>();
    services.AddTransient<ThingsService>();

    return services;
}

public IServiceCollection ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddContexts();
    services.AddCommonServices();
    services.AddOtherServices();
    return services;
}

如您所见,更加简洁易读!

创建一个静态文件,例如;

public static class StartupConfiguration
{
    public static void AddMyLogging(
        this IServiceCollection services)
    {
        services.AddSingleton<ILoggerFactory, LoggerFactory>();
        services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
        services.AddLogging(builder => builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace));
    }
}

然后在你的 Startup class:

    public void ConfigureServices(
        IServiceCollection services)
    {
        services.AddMyLogging();
    }

只调用 AddLogging 扩展方法就足够了。

services.AddLogging(builder => builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace)); 

因为,如果您查看此扩展方法的实现,您会发现 ILoggerFactoryILogger<> 已经应该添加到服务中。

services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
services.TryAdd(ServiceDescriptor.Singleton(typeof (ILogger<>), typeof (Logger<>)));