未附加调试器时自动分辨率错误

时间:2014-07-03 19:15:39

标签: .net dependency-injection autofac

我们正在使用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>();
    }
}

应用程序在容器中注册了许多其他类型(包括几个整个程序集的自动注册),但其他一切似乎都能正常工作。

我试图在一个只有最小必要类型的小项目中重现错误,但是那里不会发生错误。

有没有人知道这种行为可能是什么原因?谢谢!

2 个答案:

答案 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会找到两个可能的参数 - 你手动提供的参数和直接类型注册。

因为听起来无论如何你都无法直接解决记录器(因为它需要被解析的东西的类型),负载覆盖只是让事情变得混乱,并且可能会在工作中投入一把扳手。