分析Autofac如何實現Controller的Ioc(Inversion of Control)


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模塊實現的原理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM