Autofac是一個Ioc框架,最大的特點應該是可以不用配置文件,直接用C#代碼來注冊。
Autofac同時也提供了對於Asp.net MVC的擴展。
這里是Autofac的文檔,介紹如何在MVC項目中集成使用:
protected void Application_Start() { var builder = new ContainerBuilder(); builder.RegisterControllers(typeof(MvcApplication).Assembly); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); // Other MVC setup...
解釋一下里面的過程:
1. 首先創建一個ContainerBuilder(它會稍后為我們提供一個容器,我們可以從中取出我們所需的對象實例)
2. 注冊當前Assembly中的所有Controllers到Builder,這樣Builder就獲取了當前MVC項目中的所有Controller類型
3. 創建容器
4. 用AutofacDependencyResolver替換MVC默認的DependencyResolver
OK. 到這里, 前面的還容易理解,最后一個DependencyResolver做了什么? 要了解DependencyResolver, 需要先知道ControllerFactory
MVC中的ControllerFactory
MVC請求的過程,就是根據請求的URL找到匹配的Route, Route解析出來對應的Controller的名字, 然后根據名字,找到對應的Controller類型,然后實例化一個Controller的對象響應請求。
上面粗體標出的,就是DefaultControllerFactory做的事情,也就是它的方法CreateController方法:
public virtual IController CreateController(RequestContext requestContext, string controllerName)
CreateController方法又主要依賴於GetControllerType和GetControllerInstance方法:
protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName) protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)
看到這么多的virtual方法,是不是很激動? 這個不是明顯是讓我們繼承和override的嘛。假如我們override這里的GetControllerInstance方法,然后根據這里的controllerType從Ioc容器中獲取這個ControllerType的實例,不就萬事OK了嗎?
沒錯,繼承和重寫GetControllerInstance方法的確可以實現Controller的Ioc, 然后在Application_Start()里面,使用下面這行代碼,替換掉DefaultControllerFactory.
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory(_container));
說好的DependencyResolver呢?
其實DefaultControllerFactory中的GetControllerInstance,調用了IDependencyResolver接口定義的方法GetService獲取實例。通過繼承這個接口,替換原有的DependencyResolver, 對於MVC原有的改動更小。所以使用通過繼承IDependencyResolver 接口的方式來實現更好. 這就是開篇我們看到的:
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
IDependencyResolver借口
public interface IDependencyResolver { object GetService(Type serviceType); IEnumerableGetServices(Type serviceType); }
想看看AutofacDependencyResolver的源代碼是如何根據Type從容器中獲取實例的, 可以到這里
思考和實踐: 什么時候用到ControllerFactory
Asp.net MVC中的Area的使用,應該大家比較熟悉了。它是用來解決大的項目,多人開發的情況的。area實現的原理,是通過命名空間來區分即使名字相同的Controller的。可是無論如何,area都是在一個project里面的.
如何能夠分離area到不同的project中呢? 這里的GetControllerType方法就是很好的突破口。下次探討一下如何實現area分離到不同的project中,方便較大的項目。這也是Orchard CMS模塊實現的原理。