Asp.net mvc 4 如果使用在设置MVC 4的依赖项解析程序之前验证,简单注入器将失败

Asp.net mvc 4 如果使用在设置MVC 4的依赖项解析程序之前验证,简单注入器将失败,asp.net-mvc-4,dependency-injection,simple-injector,Asp.net Mvc 4,Dependency Injection,Simple Injector,我们有一个基于ASP.NETMVC4的应用程序,已经有几年的历史了,我正在努力消除它的一些技术债务。我正在做的一件事是引入依赖注入,这样我们可以更好地将业务逻辑与数据访问实现分离开来,并减少编写独立单元测试的痛苦。我用过简单的注射器,但我有一些问题 我一直在跟踪调查。它对初始化过程的描述如下: 创建一个容器 在容器中注册类型 验证容器(可选) 重写默认依赖项解析程序 这是目前为止在应用程序中实现的方法。为了清晰起见,我删除了日志记录语句,并为上述步骤添加了标记注释: // 1 var conta

我们有一个基于ASP.NETMVC4的应用程序,已经有几年的历史了,我正在努力消除它的一些技术债务。我正在做的一件事是引入依赖注入,这样我们可以更好地将业务逻辑与数据访问实现分离开来,并减少编写独立单元测试的痛苦。我用过简单的注射器,但我有一些问题

我一直在跟踪调查。它对初始化过程的描述如下:

  • 创建一个容器
  • 在容器中注册类型
  • 验证容器(可选)
  • 重写默认依赖项解析程序
  • 这是目前为止在应用程序中实现的方法。为了清晰起见,我删除了日志记录语句,并为上述步骤添加了标记注释:

    // 1
    var container = new Container();
    var webRequestLifestyle = new WebRequestLifestyle();
    
    // 2
    container.Register<IOrganizationService>(
        delegate
        {
            var proxy = new OrganizationServiceProxy(
                organizationServiceManagement, clientCredentials);
            proxy.EnableProxyTypes();
            return proxy;
        },
        webRequestLifestyle);
    
    container.RegisterSingle<ILoggerProvider>(LoggerProvider); // static field
    container.Register<IExternalLinkRepository, ExternalLinkRepository>(webRequestLifestyle);
    container.Register<IQueueRepository, QueueRepository>(webRequestLifestyle);
    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
    container.RegisterMvcIntegratedFilterProvider();
    
    // 3
    container.Verify(VerificationOption.VerifyAndDiagnose);
    
    // 4
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    
    默认的MVC控制器激活器不知道如何处理此问题。然而,我不明白的是,为什么Simple Injector的
    Container.Verify
    方法会点击MVC的默认控制器激活器。容器不应该固有地使用Simple Injector的依赖关系解析来测试依赖关系图吗?查看异常调用堆栈,它起源于
    System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create
    ,因此它在某个点上肯定超出了简单注入器的界限

    但是,当我交换步骤3和步骤4的顺序时:

    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    container.Verify(VerificationOption.VerifyAndDiagnose);
    
    它成功地验证了容器,并且依赖项注入在应用程序中也按预期工作。这似乎暂时解决了问题。不过,我想知道:

  • 为什么Simple Injector使用MVC的默认控制器激活器来测试依赖项解析?这是预期的/记录在案的吗
  • 先设置自定义冲突解决程序,然后验证是否有任何副作用?我这样问是因为这与文档中的指南相反。它似乎按照预期工作,如果其中任何一个失败,应用程序将崩溃,因此从应用程序的角度来看,这似乎并不重要

  • 所以,这是一个有趣的追踪。作为最后手段,应用程序尝试使用
    application\u Error
    处理未捕获的错误。在
    Application\u Start
    中执行的
    Verify()
    方法确实在验证失败时引发了异常,但这被
    Application\u Error
    方法捕获(需要弄清楚为什么没有记录,但情况不同)。因此,从未调用过
    DependencyResolver.SetResolver
    。然后,通过管道发出的实际请求将尝试使用默认的控制器激活器。当然,这些请求并没有发送给隐藏的控制器,这导致验证失败


    一个控制器还有一个静态构造函数,它缓存了一批只读数据,这些数据不需要为应用程序的每个新请求进行处理。静态构造函数由于一个bug而崩溃,这个bug阻止了该控制器的实例化,并导致应用程序停止。以更合理的方式缓存数据并删除静态构造函数后,验证工作正常,应用程序工作正常,同时根据指南再次执行DI设置。

    请添加异常(可能还有内部异常)的完整堆栈跟踪回答你的问题。但是一个简单的答案是:简单的注入器不调用依赖解析程序;这是你自己做的。检查堆栈跟踪,您将看到在某些构造函数中,您正在通过
    DependencyResolver
    解析某些内容。这是一种不好的做法,抛出此异常非常好,因为现在您有机会改进代码。没有明确使用
    DependencyResolver
    -但是,有一个失败的静态构造函数。而简单注入器引发的实际异常由于错误处理而被默默地吞噬。你把我带到了正确的轨道上,在建筑工人中寻找任何不正常的东西。谢谢感谢您指出看到的错误消息是实际潜在错误的掩码。一旦我们深入研究了所有内部异常,我们发现了一个web.config/nlog问题……与simpleinjector无关。
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    container.Verify(VerificationOption.VerifyAndDiagnose);