【问题标题】:Simple Injector and a Logging Abstraction Using Log4net使用 Log4net 的简单注入器和日志抽象
【发布时间】:2016-05-26 05:08:48
【问题描述】:

为了尝试使用 Log4net 获得良好的日志记录抽象,我从 this SO post 获取抽象,并从 this 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 记录器,它从注入的类中获取其类型。虽然大多数日志记录将在一个包罗万象的情况下完成,但我希望一些日志记录发生在较低层,例如当表单验证失败时。

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

LogImpl 类型的构造函数包含带名称的参数 'logger' 并键入未注册的 ILogger。请确保 ILogger已注册,或更改LogImpl的构造函数。

不太确定从这里去哪里,所以任何帮助将不胜感激。

编辑

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

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

【问题讨论】:

    标签: c# log4net simple-injector


    【解决方案1】:

    您指向的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);
    

    【讨论】:

    • 谢谢史蒂文。该死的,我对自己很生气。你的答案似乎很明显,我不知道为什么我没有想出它。我也花了很长时间。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多