2012-12-12 75 views
5

我正在使用Windsor日志记录工具和NLog集成工具将日志记录添加到项目中。Windsor日志记录工具:控制日志名称

我没有按照Windsor文档中建议的将Log属性添加到每个我想支持日志记录的类的做法,而是决定尝试使用动态拦截来实现它。到目前为止,拦截器是相当基础的。它只是使用构造器注入来获得​​一个实例:

class LoggingInterceptor : IInterceptor 
{ 
    private readonly ILogger _logger; 
    public LoggingInterceptor(ILogger logger) 
    { 
     if (logger == null) throw new ArgumentNullException("logger"); 
     _logger = logger; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     // just a placeholder implementation, I'm not actually planning to do this ;) 
     _logger.Info(invocation.Method.Name); 
     invocation.Proceed(); 
    } 
} 

除此之外,所有我所做的就是最小登记拦截,并把它应用到一个组件,日志工具负责其余的护理。

container.Register(Component.For<LoggingInterceptor>().LifeStyle.Transient); 

container.Register(
    Component.For<IEmployeeRepository>() 
    .ImplementedBy<EmployeeRepository>() 
    .Interceptors(InterceptorReference.ForType<LoggingInterceptor>()).First); 

到目前为止这么好 - 有点。我得到的记录器遵循NLog推荐的每个记录器的练习。在这种情况下,我不认为这是一个很好的选择。这意味着每条消息都会转到名为“MyApplication.Interceptors.LoggingInterceptor”的日志中,这不是非常有用。

我倾向于在记录器应用到抽象后命名的日志。例如,如果记录器已应用于IEmployeeRepository的实现,则日志应命名为EmployeeRepository。这是可行的吗?

编辑: 我试过实施自定义ILoggerFactory并指示容器使用它。然而,我很快遇到了一个障碍:当温莎召唤进入工厂时,唯一提供的信息是正在采集记录器的物体的类型。没有提供有关该对象的其他信息,因此ILoggerFactory无法找到拦截器已应用到的抽象。

我注意到有两个接受字符串作为参数的过载ILoggerFactory.Create()。温莎似乎没有直接使用他们中的任何一个,但有人会认为他们必须在那里出于某种原因。流利注册API中是否有可用于指定使用特定字符串的任何内容?

回答

6

这是一个与你非常相似的问题,它有一个可接受的答案。在链接中,发布答案的人建议使拦截器依赖于ILoggerFactory,并在Intercept方法中使用IInvocation.TargetType作为发送给ILoggerFactory的类型以获取适当的记录器。

请注意,我不使用Castle,所以我无法对此建议发表更多评论。

public class LoggingInterceptor : IInterceptor 
{ 
    private readonly ILoggerFactory _loggerFactory; 

    public LoggingInterceptor(ILoggerFactory loggerFactory) 
    { 
     _loggerFactory = loggerFactory; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     var logger = _loggerFactory.Create(invocation.TargetType); 
     if (logger.IsDebugEnabled) 
     { 
      logger.Debug(CreateInvocationLogString(invocation)); 
     } 
     try 
     { 
      invocation.Proceed(); 
     } 
     catch (Exception e) 
     { 
      logger.Warn(CreateInvocationLogString(invocation)); 
      throw; 
     } 
     logger.Info(CreateInvocationLogString(invocation)); 
    } 

    private static String CreateInvocationLogString(IInvocation invocation) 
    { 
     var sb = new StringBuilder(100); 
     sb.AppendFormat("Called: {0}.{1}(", invocation.TargetType.Name, invocation.Method.Name); 
     foreach (var argument in invocation.Arguments) 
     { 
      var argumentDescription = argument == null ? "null" : argument.ToString(); 
      sb.Append(argumentDescription).Append(","); 
     } 
     if (invocation.Arguments.Any()) 
     { 
      sb.Length--; 
     } 
     sb.Append(")"); 
     return sb.ToString(); 
    } 
} 

Castle: How can i get the correct ILogger in the logging interceptor?

你可能已经看到了这一点,但这里是一个城堡的例子,说明如何创建一个日志记录拦截器和如何,显然,打造包装类型的记录程序的链接:

http://docs.castleproject.org/Windsor.Introduction-to-AOP-With-Castle.ashx

编辑:ILoggerFactory为n日志的实现是ExtendedNLogFactory,它在Castle.Core-NLOG NuGet包(http://www.nuget.org/packages/Castle.Core-NLog

+1

你的Google-fu显然比我的好。这应该是完美的 - 唯一的额外细节是获取一个为抽象类型而不是具体类型命名的日志。我想我会通过搜索具体类型的接口来查找遵循约定的接口。 –

+0

很高兴我能够帮助! – wageoghe