为了尝试使用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记录器,它从注入它的类中获取Type。虽然大多数日志记录都是在全部进行中进行的,但我希望在较低层进行一些日志记录,例如表单验证失败时。
我使用该配置获得的ActivationException
是:
LogImpl类型的构造函数包含带名称的参数 &#39;记录器&#39;并键入未注册的ILogger。请确保 ILogger已注册,或更改LogImpl的构造函数。
不太确定从哪里开始,所以任何帮助都会受到赞赏。
修改
抱歉,我应该指出我正在尝试编写它,以便我只需要编写一次此配置。以下工厂功能有效,但我不想每次要注入记录器时手动添加更多配置:
container.RegisterPerWebRequest<ILog>(() => LogManager.GetLogger(typeof(LoginController)));
答案 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);