asp.net-mvc – Autofac:解决最内层范围的任何方法?
在过去几年中使用过Ninject,Castle Windsor和其他IoC容器之后,我正在尝试使用新的ASP.NET MVC项目中的Autofac.因此,虽然我一般都了解IoC容器,但我对Autofac还不熟悉,而且我仍然在寻找一些最佳实践.
目前我正在试图找出是否有办法解决最里面的嵌套范围. 我有以下情况:注册为SingleInstance()的组件具有创建嵌套生命周期范围的方法,提供配置操作以将某些组件配置为InstancePerLifetimeScope,并且在此嵌套范围内解析已注册的组件以执行有用的操作,像这样: ILifetimeScope currentScope = ???; using (var scope = currentScope.BeginLifetimeScope(cb => { cb.RegisterType<X>().InstancePerLifetimeScope(); // ... })) { var comp = scope.Resolve<X>(); // ... } 问题是我希望currentScope成为最里面的生命周期范围,因为我知道X依赖于最里面范围内的组件.在最简单的情况下,例如当前请求的生命周期范围.我当然可以使用AutofacDependencyResolver.Current.RequestLifetimeScope来获取它,但我不想使用它,因为它不是真的可以测试.而且,寿命范围不一定是最里面的. 那么,有没有办法找到最里面的寿命范围,例如根容器还是不同的ILifetimeScope? 解决方法
在Autofac中,最里面的范围始终是容器.使用AutofacDependencyResolver,它就是
AutofacDependencyResolver.Current.ApplicationContainer 嵌套范围(如果你只有一个ILifetimeScope)无法“向后走”以到达容器.无论如何,我不一定确定你想这样做. 听起来你的SingleInstance组件正在做某种服务定位,基本上是通过手动注册/解析某些组件.如果注册的类型集是固定的,我可能会建议(如果可能的话)对系统进行一些重新设计,因此SingleInstance组件不再被注册为SingleInstance,而是被注册为InstancePerDependency,然后将这些其他项目作为构造函数参数. 代替… // Consuming class like this... public class BigComponent { public void DoSomethingCool() { using(var scope = ...) { var c = scope.Resolve<SubComponent>(); c.DoWork(); } } } // ...and container registrations like this... builder.RegisterType<BigComponent>().SingleInstance(); 您可能会尝试反转一下: // Consuming class like this... public class BigComponent { private SubComponent _c; public BigComponent(SubComponent c) { _c = c; } public void DoSomethingCool() { _c.DoWork(); } } // ...and container registrations like this... builder.RegisterType<BigComponent>().InstancePerDependency(); builder.RegisterType<SubComponent>().InstancePerLifetimeScope(); 我们的想法是不必进行动态注册和即时解决的事情. 如果您遇到服务定位,如果您需要绝对最内层范围,则需要使用AutofacDependencyResolver.Current.ApplicationContainer,但请记住,如果您这样做,那么您注册为InstancePerHttpRequest的任何对象将无法解析,因此您可能会遇到麻烦.建议使用AutofacDependencyResolver.Current.RequestLifetimeScope.这会使你的方法: var requestScope = AutofacDependencyResolver.Current.RequestLifetimeScope; using (var scope = requestScope.BeginLifetimeScope(cb => { cb.RegisterType<X>().InstancePerLifetimeScope(); // ... })) { var comp = scope.Resolve<X>(); // ... } 在测试环境中,AutofacDependencyResolver允许您交换指示如何生成请求生存期的提供程序.您可以实现这样的简单/存根: public class TestLifetimeScopeProvider : ILifetimeScopeProvider { readonly ILifetimeScope _container; private ILifetimeScope _lifetimeScope = null; public TestLifetimeScopeProvider(ILifetimeScope container) { if (container == null) throw new ArgumentNullException("container"); _container = container; } public ILifetimeScope ApplicationContainer { get { return _container; } } public ILifetimeScope GetLifetimeScope() { if (_lifetimeScope == null) { _lifetimeScope = ApplicationContainer.BeginLifetimeScope("httpRequest") } return _lifetimeScope; } public void EndLifetimeScope() { if (_lifetimeScope != null) _lifetimeScope.Dispose(); } } 同样,只是用于单元测试的存根,而不是您在生产中使用的存根. 然后,当您在测试中连接DependencyResolver时,您将提供您的生命周期范围提供者: var lsProvider = new TestLifetimeScopeProvider(container); var resolver = new AutofacDependencyResolver(container,lsProvider); DependencyResolver.SetResolver(resolver); 这使您可以使用InstancePerHttpRequest和此类内部单元测试,而无需实际具有实际请求上下文.这也意味着您应该能够在注册/解决方法中使用请求生命周期范围,而不必依赖于应用程序容器. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ASP.NET – 构建自己的路由系统
- .net – CS0012:类型’System.Data.Linq.DataContext’在未
- ASP.NET-MVC 2 RC最佳功能
- asp.net-mvc – 使用Asp.Net MVC创建私人照片库
- asp.net-mvc – @helper和Url.Action
- ASP.NET -- WebForm -- HttpResponse 类的方法和属性
- .net – 在MVC应用程序之间共享视图,逻辑等
- 如何在ASP.NET中以程序方式模拟HTTP POST?
- yield在WCF中的错误使用——99%的开发人员都有可能犯的错误
- asp.net-mvc-3 – Telerik().ScriptRegistrar()如何防止加载