Agenda
前言
產生Controller
物件相關物件關係如下面UML圖
透過ControllerFactory
建立一個Controller
控制器物件.而ControllerFactory
依賴IControllerActivator
物件產生Controller
.
上面IControllerActivator
可以透過建立使用我們的依賴注入容器來替換原本反射產生物件.
DependencyResolver
是MVC提供的一個可替換物注入點,今天我們會藉由他來我們實現注入MVC方式.
Aufofac依賴注入容器
在實現自己的DependencyResolver
前先談談Autofac容器做甚麼用的?
我之前有寫一篇IOC(控制反轉),DI(依賴注入) 深入淺出~~,講述IOC(控制反轉),DI(依賴注入)這兩個設計技巧的理念核心.
言簡意賅可以統一交由容器來幫忙管理物件生命週期和建立方式,也管理物件相依性,兩個重點我們使得只需要提供使用類別的特徵(型別或其他可辨別特徵),容器就提供給我們相對應的物件.
在Autofac
有需多使用方式這裡就不一一介紹,有興趣讀者可以上網google
或是查閱Autofac
官方文件
IDependencyResolver介面
DependencyResolver
是一個靜態物件,MVC application使用同一個解析器(DefaultDependencyResolver
)而他有一個SetResolver
方法可以替換成其他DependencyResolver
IDependencyResolver
有兩個方法需要實現.
1 | public interface IDependencyResolver |
MVC依賴於GetService
和GetServices
,取得物件實例並提供一個抽象提供外部提供修改或擴充.
預設使用(DefaultDependencyResolver
)這個解析器來取得我們物件(DefaultDependencyResolver
解析器使用Activator.CreateInstance(serviceType);
建立物件)
建立CustomerDependencyResolver(IDependencyResolver)
這邊我們利用autofac
來完成建立物件動作,先建立一個ILifetimeScope _container
由建構子注入此物件.
1 | public class CustomerDependencyResolver : IDependencyResolver |
在GetService
呼叫ResolveOptional
方法透過Type
到容器中搜尋匹配的物件並返回.
CustomerControllerActivator(IControllerActivator)
IControllerActivator
有一個Create
方法,ControllerFacotry
靠它來幫我們產生使用Controller
物件,而我們在這邊建立自己IControllerActivator
並在Create
方法中實現自己得邏輯.透過DependencyResolver
來產生物件(替換成CustomerDependencyResolver
)
1 | public class CustomerControllerActivator : IControllerActivator |
我們會在Autofac
容器註冊目前Assembly
所有繼承IController
物件.
1 | //注入typeof(MvcApplication).Assembly 中所有繼承IController物件. |
在上面CustomerControllerActivator.Create
會透Autofac
解析器幫我們建立Controller
在Application_Start中MVC替換成自己的解析器
首先利用
ControllerBuilder
的SetControllerFactory
方法,重新替換使用ControllerFacotry
.在利用
builder.RegisterControllers
注入typeof(MvcApplication).Assembly
中所有繼承IController
物件.註冊
IMemberService
介面物件(裡面有一個int GetMemberBalance(int memberId);
方法來模擬取得會員餘額)DependencyResolver.SetResolver(new CustomerDependencyResolver(builder.Build()))
替換成我們使用的解析器
因為
ControllerFacotry
預設使用DefaultControllerActivator
,而我們需要替換成自己建立得CustomerControllerActivator
並利用容器來幫我們注入.
1 | public class MvcApplication : HttpApplication |
在Controller使用注入
HomeController
控制器中在建構子注入,並呼叫IMemberService.GetMemberBalance
方法
執行專案請求Home/About
頁面可以看到ViewBag.Message
已經成功顯示一個HardCode餘額了.
1 | public class HomeController : Controller |
小結:
DefaultControllerActivator
使用反射建立一個Controller
物件
然而IControllerActivator
提供一個產生Controller
接口,而我們可以藉由實現此介面並使用DependencyResolver
靜態物件產生Controller
物件(藉由容器框架產生).
最後會把Controller
依賴物件藉由依賴注入容器注入進去.
Github範例程式原始碼 CustomerContainer
分支上
此文作者:Daniel Shih(石頭)
此文地址: https://isdaniel.github.io/ithelp-day27/
版權聲明:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!