我们正在使用Autofac来构建我们的应用程序,以及基于Log4Net的日志记录机制。遵循Log4Net样式,在其构造函数中请求ILogger
的每个对象都获得Log4NetLogger
(我们自己的包装类)的实例,该实例又获取传递给其构造函数的请求对象的类型。
要使用Autofac执行此操作,我们正在使用此功能(我相信我在此处找到了某处):
public class LoggingModule : Module
{
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration)
{
registration.Preparing += OnComponentPreparing;
}
private void OnComponentPreparing(object sender, PreparingEventArgs e)
{
var t = e.Component.Activator.LimitType;
e.Parameters = e.Parameters.Union(new[]
{
new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => new Log4NetLogger(t))
});
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Log4NetLogger>().As<ILogger>();
}
}
这很有效 - 只要应用程序在Visual Studio中运行,并附带调试器。如果它自己运行,则在第一次尝试解析ILogger
时失败:
Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Application.Infrastructure.Logging.Log4NetLogger' can be invoked with the available services and parameters:
Cannot resolve parameter 'System.Type type' of constructor 'Void .ctor(System.Type)'.
使用此模块替换上述注册可以修复错误,但当然会导致丢失有关日志条目来自哪个类的信息:
public class SimpleLoggingModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterInstance(new Log4NetLogger(typeof(object))).As<ILogger>();
}
}
应用程序在容器中注册了许多其他类型(包括几个整个程序集的自动注册),但其他一切似乎都能正常工作。
我试图在一个只有最小必要类型的小项目中重现错误,但是那里不会发生错误。
有没有人知道这种行为可能是什么原因?谢谢!
答案 0 :(得分:0)
我刚刚测试了一个适合我的解决方案。有一种特定的方法来编写使用ResolvedParameters
的注册更换注册行:
builder.RegisterType<Log4NetLogger>().As<ILogger>();
使用:
builder.RegisterType<Log4NetLogger>().As<ILogger>().
WithParameter((pi, c) => pi.ParameterType == (typeof(Type)), (pi, c) => typeof(ILogger));
我使用一些存根类对此进行了测试,但至少调用var logger = container.Resolve<ILogger>();
返回了一个实例并且没有抛出异常。
答案 1 :(得分:0)
尝试删除“加载覆盖”并仅执行事件处理。
Autofac wiki上有一个log4net集成模块的示例: https://github.com/autofac/Autofac/wiki/Log4-Net-Integration
我猜测问题是当你解决需要记录器的东西时,Autofac会找到两个可能的参数 - 你手动提供的参数和直接类型注册。
因为听起来无论如何你都无法直接解决记录器(因为它需要被解析的东西的类型),负载覆盖只是让事情变得混乱,并且可能会在工作中投入一把扳手。