简单的注入器和使用Log4net的日志抽象

时间:2016-05-26 05:08:49

标签: c# log4net simple-injector

为了尝试使用Log4net获得一个很好的日志记录抽象,我从this SO postthis SO post的适配器中获取了抽象,并尝试让它们一起工作。

真正剩下要做的就是配置容器,这是我没有成功完成的部分。

我试过的配置是

public static class InfrastructureRegistry
{
    public static void RegisterLoggingServices(this Container container)
    {
        container.RegisterConditional(typeof(ILog), c => LogManager.GetLogger(
            c.Consumer.ImplementationType).GetType(), 
            Lifestyle.Scoped, c => true);
        container.RegisterPerWebRequest<ILogger, Log4netAdapter>();
    }
}

从代码中可以看出,我想要一个特定的log4net记录器,它从注入它的类中获取Type。虽然大多数日志记录都是在全部进行中进行的,但我希望在较低层进行一些日志记录,例如表单验证失败时。

我使用该配置获得的ActivationException是:

  

LogImpl类型的构造函数包含带名称的参数   &#39;记录器&#39;并键入未注册的ILogger。请确保   ILogger已注册,或更改LogImpl的构造函数。

不太确定从哪里开始,所以任何帮助都会受到赞赏。

修改

抱歉,我应该指出我正在尝试编写它,以便我只需要编写一次此配置。以下工厂功能有效,但我不想每次要注入记录器时手动添加更多配置:

container.RegisterPerWebRequest<ILog>(() => LogManager.GetLogger(typeof(LoginController)));

1 个答案:

答案 0 :(得分:4)

您指向的example adapter假定应用程序中的每个组件都有一个记录器,而您希望拥有一个“知道”其消费者的特定记录器,因此它可以将日志消息与原创阶级。

虽然在使用log4net和NLog等工具时这似乎是一种非常常见的做法,但根据我的经验,这个要求通常来自于在代码中太多地方完成日志记录的事实。有关详细信息,请阅读this stackoverflow q/a

也就是说,如果要有条件地注册记录器,则必须将适配器更改为泛型类;这样你可以使注册成为条件:

public class Log4netAdapter<T> : ILogger
{
    private static readonly log4net.ILog logger = LogManager.GetLogger(typeof(T));

    public void Log(LogEntry entry)
    {
        if(entry.LoggingEventType == LoggingEventType.Information)
            logger.Info(entry.Message, entry.Exception);
        else if(entry.LoggingEventType == LoggingEventType.Warning)
            logger.Warn(entry.Message, entry.Exception);
        else if(entry.LoggingEventType == LoggingEventType.Error)
            logger.Error(entry.Message, entry.Exception);
        else
            logger.Fatal(entry.Message, entry.Exception);
    }
}

使用此泛型类,您可以执行以下条件/上下文注册:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Log4netAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);