C# 简单喷油器:寄存器ILogger<;T>;通过使用iLogger Factory.CreateLogger<;T>;()

C# 简单喷油器:寄存器ILogger<;T>;通过使用iLogger Factory.CreateLogger<;T>;(),c#,dependency-injection,simple-injector,microsoft-extensions-logging,C#,Dependency Injection,Simple Injector,Microsoft Extensions Logging,我正在处理一个项目,它使用简单的注入器作为依赖注入器。另一方面,此项目使用Microsoft.Extensions.Logging来记录某些类中发生的事件 我的技术问题很容易解释。 我想在我的DI中注册ILogger,独立于正在调用的类T,但是我确实需要从我的ILogger工厂.CreateLogger()方法注册,因为这使用Microsoft.Extensions.configuration获取记录器配置 我需要使用类似这样的东西来实例我的记录器: private Microsoft.Exte

我正在处理一个项目,它使用简单的注入器作为依赖注入器。另一方面,此项目使用Microsoft.Extensions.Logging来记录某些类中发生的事件

我的技术问题很容易解释。 我想在我的DI中注册ILogger,独立于正在调用的类T,但是我确实需要从我的
ILogger工厂.CreateLogger()
方法注册,因为这使用
Microsoft.Extensions.configuration
获取记录器配置

我需要使用类似这样的东西来实例我的记录器:

private Microsoft.Extensions.Logging.ILogger CreateLogger<T>()
{
     var factory = this.ResolveService<ILoggerFactory>();
     var logger = factory.CreateLogger<T>();
     return logger;
}
private Microsoft.Extensions.Logging.ILogger CreateLogger()
{
var factory=this.ResolveService();
var logger=factory.CreateLogger();
返回记录器;
}
我可以通过以下方式实现注射:

Container.Register(typeof(ILogger<>), typeof(Logger<>));
Container.Register(typeof(ILogger)、typeof(Logger));
这使我们能够解决如下问题:

public class SomeApiController : ApiController
{
     public SomeApiController(ILogger<SomeApiController> logger)
     {
         //logger is well instantiated, but doesn't got the configuration
         logger.LogInformation("test log.");
     }
}
公共类SomeApiController:ApiController
{
公共控制器(ILogger记录器)
{
//logger被很好地实例化了,但是没有得到配置
logger.LogInformation(“测试日志”);
}
}
但是正如我所说的,这样做没有经过从
Microsoft.Extensions.Logging.ILoggerFactory
类获得的配置,所以这没有什么用处


是否有方法通过使用my
CreateLogger
注册
ILogger

使用以下注册:

container.RegisterInstance(loggerFactory);
容器.RegisterSingleton(typeof(ILogger),typeof(Logger));
或者,如果要将Simple Injector集成到通用主机或ASP.NET Core应用程序中,请使用扩展方法甚至将非通用的
ILogger
注入到应用程序组件中,如此ASP.NET Core
Startup
类中所示:

公共类启动
{
...
public void配置服务(IServiceCollection服务)
{
services.AddLogging();//将日志添加到框架中
//AddSimpleInjector启用“交叉布线”,这意味着您可以
//简单喷油器解决了依赖于通用喷油器的部件问题
//伊洛格抽象。
services.AddSimpleInjector(容器,选项=>
{
options.AddAspNetCore();
//AddLogger允许简单的喷油器解析组件依赖
//非通用的Microsoft.Extensions.Logging.ILogger接口。
//简易喷射器将自动喷射正确的ILogger
//给你。
options.AddLogging();
});
}
...
}
有关完整示例,请参见

让应用程序组件依赖于
ILogger
而不是
ILogger
,可以使您的代码更简单、更易于测试,并且更不容易出错。如果您使用的是不带(
i记录器
)的简单注入器(如前一个示例所示,您可以使用以下注册来确保每当注入
i记录器
时,仍然注入正确的
记录器

container.register条件(
类型(ILogger),
c=>typeof(Logger).MakeGenericType(c.Consumer.ImplementationType),
生活方式,单身,
_=>正确);
这确保每个应用程序组件都有自己的
Logger
实例,其中
T
是记录器注入到的组件的类型。以下面的类为例,它取决于
ILogger

公共类组件A:iSeries设备
{
公共组件A(ILogger记录器){…}
}
上述注册将确保
组件a
被注入
记录器
,即使它仅仅依赖于
ILogger
,而不是
ILogger

如果上面的内容适合你的需要,你可以停止阅读这里的内容……如果你对更为坚实的解决方案感兴趣,可以继续阅读

固溶体 除了让应用程序组件依赖于框架定义的
ILogger
抽象之外,您还可以选择定义特定于应用程序的记录器抽象,如(DIP)所述

DIP声明抽象应由应用程序本身定义,这意味着您可以定义自己的(也请参阅以了解您为什么要这样做的解释),并在此基础上构建一个适配器,如所述。您可以简单地从所述的
MicrosoftLoggingAdapter
派生通用适配器,如下所示:

公共密封类MicrosoftLoggingAdapter:MicrosoftLoggingAdapter
{
公共MicrosoftLoggingAdapter(iLogger工厂)
:base(factory.CreateLogger()){}
}
使用此通用适配器,您可以按如下方式配置简单喷油器:

container.RegisterInstance(工厂);
容器注册表条件(
typeof(MyApplication.Abstractions.ILogger),
c=>typeof(MicrosoftLoggingAdapter).MakeGenericType(c.Consumer.ImplementationType),
生活方式,单身,
_=>正确);

基于Steven的解决方案,我发布我的答案以帮助其他人:

    private void RegisterServices()
    {
        Container.Register(ConfigureLogger, Lifestyle.Singleton);            
        Container.Register(typeof(ILogger<>), typeof(LoggingAdapter<>));
    }

    private ILoggerFactory ConfigureLogger()
    {
        LoggerFactory factory = new LoggerFactory();

        var config = new ConfigurationBuilder()
            .AddJsonFile("logging.json")
            .Build();

        //serilog provider configuration
        var log = new LoggerConfiguration()
                 //.ReadFrom.Configuration(config)
                 .WriteTo
                 .RollingFile(ConfigSettings.LogsPath)
                 .CreateLogger();

        factory.AddSerilog(log);

        return factory;
    }

    public class LoggingAdapter<T> : ILogger<T>
    {
        private readonly Microsoft.Extensions.Logging.ILogger adaptee;          

        public LoggingAdapter(ILoggerFactory factory)
        {
            adaptee = factory.CreateLogger<T>();
        }

        public IDisposable BeginScope<TState>(TState state)
        {
            return adaptee.BeginScope(state);
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return adaptee.IsEnabled(logLevel);
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            adaptee.Log(logLevel, eventId, state, exception, formatter);
        }
    }   
private void RegisterServices()
{
容器.Register(ConfigureLogger,Lifestyle.Singleton);
容器寄存器(typeof(ILogger)、typeof(LoggingAdapter));
}
专用iLogger工厂配置记录器()
{
LoggerFactory工厂=新LoggerFactory();
var config=new ConfigurationBuilder()
.AddJsonFile(“logging.json”)
.Build();
//serilog提供程序配置
var log=new LoggerConfiguration()
//.ReadFrom.Configuration(配置)
.书面
.RollingFile(ConfigSettings.LogsPath)
.创造