Asp.net mvc 4 如果使用在设置MVC 4的依赖项解析程序之前验证,简单注入器将失败
我们有一个基于ASP.NETMVC4的应用程序,已经有几年的历史了,我正在努力消除它的一些技术债务。我正在做的一件事是引入依赖注入,这样我们可以更好地将业务逻辑与数据访问实现分离开来,并减少编写独立单元测试的痛苦。我用过简单的注射器,但我有一些问题 我一直在跟踪调查。它对初始化过程的描述如下: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
// 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);
它成功地验证了容器,并且依赖项注入在应用程序中也按预期工作。这似乎暂时解决了问题。不过,我想知道:
所以,这是一个有趣的追踪。作为最后手段,应用程序尝试使用
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);