简单注入器和使用Log4net的记录抽象 [英] Simple Injector and a Logging Abstraction Using Log4net

查看:125
本文介绍了简单注入器和使用Log4net的记录抽象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了尝试使用Log4net获得不错的日志记录抽象,我从这篇SO帖子此SO帖子中的适配器,并试图使它们一起工作.

In order to try and get a nice logging abstraction with Log4net, I took the abstraction from this SO post and the adapter from this SO post and tried to get them working together.

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

All that was really left to do was configure the container and that is the part which I have not succeeded in doing.

我尝试过的配置是

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.虽然大多数日志记录将在一个包罗万象的地方完成,但我希望某些日志记录可以在较低的层中进行,例如表单验证失败时.

As you can see from the code, I would like a specific log4net logger which takes its Type from the class into which it is injected. Whilst most logging would be done in a catch-all, I want some logging to happen in lower layers e.g. when a form validation fails.

通过该配置获得的ActivationException是:

LogImpl类型的构造函数包含名称为的参数 'logger',然后输入未注册的ILogger.请确保 已注册ILogger,或更改LogImpl的构造函数.

The constructor of type LogImpl contains the parameter with name 'logger' and type ILogger that is not registered. Please ensure ILogger is registered, or change the constructor of LogImpl.

不太确定从这里去哪里,所以将不胜感激.

Not quite sure where to go from here, so any help would be appreciated.

修改

对不起,我应该指出,我正在尝试编写它,这样我只需要编写一次此配置即可.以下工厂功能有效,但我不想每次想插入记录器时都必须手动添加更多配置:

Sorry, I should point out that I am trying to write it such that I only have to write this config once. The following factory function works, but I don't want to have to manually add more config every time I want to inject a logger:

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

推荐答案

The example adapter you point at assumes a single logger for every component in the application, while what you wish is to have a specific logger that 'knows' about its consumer, so it can relate the log messages to the originating class.

尽管在使用log4net和NLog之类的工具时,这似乎是非常普遍的做法,但根据我的经验,此要求通常来自于在代码中的太多地方进行日志记录的事实.有关更多信息,请阅读此stackoverflow q/a .

Although this seems to be a very common practice when working with tools like log4net and NLog, in my experience, this requirement often comes from the fact that logging is done at too many places in the code. Please read this stackoverflow q/a for more information.

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

That said, if you want to register the logger conditionally, you will have to change the adapter to a generic class; that way you can make the registration conditional:

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);
    }
}

使用此通用类,您可以进行以下条件/上下文注册:

With this generic class, you can do the following conditional/contextual registration:

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

这篇关于简单注入器和使用Log4net的记录抽象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆