设置log4net记录器的名称

时间:2011-01-24 15:00:44

标签: logging log4net asp.net-mvc-3 castle-windsor

我在我的应用程序(MVC3 Web应用程序)中使用带有log4net的Castle日志记录工具。但是,我没有直接使用ILogger接口,而是通过使用具体实现Log4NetAuditor创建另一个接口(IAuditor)来抽象它(参见下面的代码)。

你可能会问我为什么要这样做,因为ILogger的意思是抽象底层日志记录实现。我这样做是因为严格遵守了抽象所有基础设施问题的onion architecture原则。

现在,除了所有记录器的名称相同外,这个工作正常:MyProject.Infrastructure.Log4NetAuditor:

2011-01-24 13:26:11,746 [11] DEBUG MyProject.Infrastructure.Log4NetAuditor [] - Attempting login...
2011-01-24 13:26:11,845 [11] DEBUG MyProject.Infrastructure.Log4NetAuditor [] - Authentication result is Authenticated

IAuditor作为AuditableComponent的属性公开,AuditableComponent是一个抽象类,所有需要日志记录的组件都来自该类。

public abstract class AuditableComponent
{
    private IAuditor _auditor = NullAuditor.Instance;

    public IAuditor Auditor
    {
        get { return _auditor; }
        set { _auditor = value; }
    }

    //....
}

Log4NetAuditor类如下所示:

public class Log4NetAuditor : IAuditor
{
    private ILogger _logger = NullLogger.Instance;

    public ILogger Logger
    {
        get { return _logger; }
        set { _logger = value; }
    }

    public void Trace(string message)
    {
        _logger.Debug(message);
    }
}

现在,很明显为什么所有日志语句都具有相同的记录器名称:ILogger是在Log4NetAuditor类上注入的。

那么,我如何确保记录器的名称对应于扩展AuditableComponent的类的名称?

1 个答案:

答案 0 :(得分:1)

我做了同样的事情,但我还包括一个静态LogManager类,它是实例化记录器的工作。我在Logger类(您的审计员类)中使我的构造函数内部化,因此无法直接创建它们。这意味着任何外部实体都需要通过LogManager类获取它们的引用。

public static class LogManager
{
    public static readonly ILogger Log = CreateLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    /// <summary>
    /// Creates the logger for the specified type.
    /// </summary>
    /// <param name="loggerType">Type of the logger.</param>
    /// <returns></returns>
    public static Logger CreateLogger(Type loggerType)
    {
        return new Logger(loggerType);
    }

    /// <summary>
    /// Creates the logger for the specified name.
    /// </summary>
    /// <param name="loggerName">Name of the logger.</param>
    /// <returns></returns>
    public static Logger CreateLogger(string loggerName)
    {
        return new Logger(loggerName);
    }
}

现在这些类型将能够将您自己的类型传递给Create方法来实例化Auditor。

更新 -

我也使用Unity容器将依赖项注入此代码中。相关位是InjectionFactory。它允许我在本地指定静态方法以根据某些条件注入类型。

DependencyInjection.Container.RegisterType<IFormatter>(
    new ContainerControlledLifetimeManager(),
    new InjectionFactory(c => CreateFormatter(filename, outputType)));

...

        private static IFormatter CreateFormatter(string filename, OutputType outputType)
        {
            TextWriter textWriter = (filename.Length > 0) ? new StreamWriter(filename) : new StreamWriter(Console.OpenStandardOutput());
            var formatter = (outputType == OutputType.Xml) ? (IFormatter)new XmlFormatter(textWriter) : new CsvFormatter(textWriter);

            return formatter;
        }

...
// Calling it
using (var formatter = DependencyInjection.Container.Resolve<IFormatter>())
{
    if (timeLimit <= 1000) retval = OutputResults(results, formatter, msxQuery);
    else TimedOutputResults(results, formatter, msxQuery, timeLimit, OutputResults);
}

嗯,这至少对我有用了!