如何使用AutoFac解析正确的记录器类型?

我正在更新使用AutoFac的遗留项目,我想将NLog与简单记录外观(SLF)一起使用

我以前在Ninject中使用过它,设置起来非常简单,我只需要做类似的事情:

kernel.Bind().ToMethod(x => LoggerFactory.GetLogger(x.Request.Target.Member.ReflectedType)); 

输出将是这样的:

NLogNinjectSlf.Services.MyService 2013-12-30 15:21:10.5782 DEBUG日志从注入的Logger

小菜一碟

但现在我必须使用AutoFac,我不知道如何获得需要记录器的Target类型

例如,如果我有以下接口/类:

 public interface IMyService { void DoSomething(); } public class MyService : IMyService { private readonly ILogger _logger; public MyService(ILogger logger) { _logger = logger; } public void DoSomething() { _logger.Debug("Log from injected Logger"); } } 

我希望能够获得MyService类的类型,将其用作记录器的名称

在AutoFac中,这是我到目前为止所尝试的:

 var containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType().As(); containerBuilder.Register(x => { // TODO: Get the correct type return LoggerFactory.GetLogger(x.GetType()); }).As(); 

顺便说一句:我在SLF4Net后面使用NLog并不是真正需要解决主要问题的…

谢谢nemesv帮助了我很多

这是我最终使用的代码

BTW。 您可以根据需要删除注入属性的代码,然后在所有类中使用DI来注入可提高性能的ILogger

 public class LoggingModule : Module { protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) { registration.Preparing += OnComponentPreparing; registration.Activated += (sender, e) => InjectLoggerProperties(e.Instance); } private static void InjectLoggerProperties(object instance) { var instanceType = instance.GetType(); // Get all the injectable properties to set. // If you wanted to ensure the properties were only UNSET properties, // here's where you'd do it. var properties = instanceType .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(ILogger) && p.CanWrite && p.GetIndexParameters().Length == 0); // Set the properties located. foreach (var propToSet in properties) { propToSet.SetValue(instance, LoggerFactory.GetLogger(instanceType), null); } } private void OnComponentPreparing(object sender, PreparingEventArgs e) { var t = e.Component.Activator.LimitType; e.Parameters = e.Parameters.Union( new[] { new ResolvedParameter((p, i) => p.ParameterType == typeof (ILogger), (p, i) => LoggerFactory.GetLogger(t)) }); } } 

然后注册模块:

 containerBuilder.RegisterModule(); 

似乎使用Autofac 4.3.0您可以简单地使用OnComponentPreparing()回调而无需使用特殊属性注入技术。 将注入ctor()和属性值:

 public class LoggingModule : Module { protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) { registration.Preparing += Registration_Preparing; } private static void Registration_Preparing(object sender, PreparingEventArgs e) { var t = e.Component.Activator.LimitType; e.Parameters = e.Parameters.Union( new[] { new ResolvedParameter( (p, i) => p.ParameterType == typeof (ILog), (p, i) => LogFactory.CreateWithType(t)) }); } } 

另外,我发现了一些很好的技巧,只有当你需要控制记录器的生命周期时才可以用于属性注入。

 public class LoggingModule : Module { protected override void Load(ContainerBuilder builder) { const string propertyNameKey = "Autofac.AutowiringPropertyInjector.InstanceType"; builder.RegisterType() .As() .OnPreparing(x => { var firstParam = x.Parameters? .OfType() .FirstOrDefault(p => p.Name == propertyNameKey); if (null == firstParam) { return; } var valueType = firstParam.Value; x.Parameters = x.Parameters.Union( new[] { new ResolvedParameter( (p, i) => p.Name == "type", (p, i) => valueType) }); }) .InstancePerDependency(); 

NLogLogger本身就在哪里

 public class NLogLogger : ILog { private readonly Logger _log; public NLogLogger() { _log = LogManager.GetCurrentClassLogger(); } public NLogLogger(Type type) { _log = LogManager.GetLogger(type.FullName); } }