選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
3 分鐘閱讀時間 (568 個字)

Autofac 內部運作如何幫助 .NET MVC Controller 做到 DI - 概述運作圖解

logoAutofac

Autofac 可以協助達成 IOC、DI 的目的,內部如何達成可以參考此篇"Autofac 套件如何達成IOC 目的- 概述圖解" 內容。套件也可以協助幫忙達成MVC架構的DI,使用上其實非常方便。但在一番了解 Autofac 初步的運作後,有些想知道運作原理傾向的開發者大多也會對如何達成 .NET MVC 之 DI 這個原理有些好奇,怎麼對MVC Controller建構子參數做Resolve的? 

所以概述如何做到DI的目的,會分以下順序

  1. 開發者如何於 .NET MVC 架構使用Autofac
  2. MVC 架構生成 Controller 之過程圖解
  3. Autofac 如何於MVC辦到DI之簡述
  4. 以簡單的例子作範例

以下會進行相關描述:

1. 如何於 .NET MVC 架構使用Autofac

首先要先於 .NET MVC 專案安裝 Autofac.Integration.Mvc 套件。安裝完成後,一樣要先在 Global.asax.cs 的 Application_Start 進行設定,對 MVC Controller 的類別註冊服務。程式為:


var builder = new Autofac. ContainerBuilder();

builder.RegisterControllers(typeof(MvcApplication).Assembly);


然後控制項類別註冊後,接著可為這些類別所要使用的物件做註冊服務。舉個例子,於 HomeController,加上一個有參數的建構子(另外有一個ILog的欄位成員):


ILog log;

public HomeController(ILog pLog){

  log = pLog;

  ...

}


如果沒有DI的協助,我們需要在每個類別中某處去做

ILog log = new ClsLog();

但是如果有幾十個Controller都要用到此ClsLog物件,如果某天要換物件的名稱內容,避免不了要改幾十次,開發效率就降低了。

所以我們要 Autofac DI 的協助。接著進行 ClsLog 的註冊服務:

builder.RegisterType<ClsLog>().As<ILogC>();

最後,建立容器與完成服務最終註冊:


var container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


DependencyResolver 是 System.Web.Mvc的物件,AutofacDependencyResolver 是 Autofac.Integration.Mvc的物件。 這邊建構好 Autofac 容器後,只要叫用到 HomeController都會注入 ClsLog 實體給建構子參數。


2. MVC 架構生成 Controller 之過程圖解

那Autofac如何對MVC Controller建構子參數做Resolve的?

首先要研究MVC是如何產生Controller。下圖為 MVC 5 產生Controller 實體的過程簡圖: 

MVC 5 產生Controller 實體並執行 Action Method 流程

 上圖中,紅色框部分是產生Controller實體的關鍵時間點。MvcHandler會去取得生成 Controller 的 Factory,此Factory之前的初始化會建構 DependencyResolver,將 Controller 類別依照 Type 來產生實體,更進一步使用的是 System.Reflection組件。

3. Autofac 如何於MVC辦到DI之簡述

如果AutoFac 要進行切入,勢必要於上一點提到的這個關鍵的時間點,改讓Autofac來做Resolve,將建構子參數做遞迴的Resolve (參考"Autofac 套件如何達成IOC 目的- 概述圖解")。

Autofac.Integration.Mvc 組件也改寫了套用 IDependencyResolver 的類別,將 GetService 改為由 Autofac組件的擴增函式來執行:


public virtual object GetService(Type serviceType)

{

     return ResolutionExtensions.ResolveOptional(this.RequestLifetimeScope, serviceType);

}


於是,Controller的Type被送入後,接著就會跑 Autofac 組件的 TryResolveService、ResolveComponent,然後遞迴將建構子的參數再進行Resolve。

而什麼時候會替換Autofac.Integration.Mvc的這個 IDependencyResolver 內容? 就是第一點說明的建立容器與完成服務最終註冊:


var container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


這邊會將 IDependencyResolver 進行替換。


4.以簡單的例子作範例

看到這邊應該多少了解關鍵的時間點替換由Autofac來接手做Resolve Controller類別,至少知道有這件事的存在。

用簡單的例子,來實現 MVC Controller Constructor Parameter DI

於 Global.asax.cs 的 Application_Start 進行設定: 

最後Controller建構子會接到所註冊的Service: 

如上參數的實體記憶體為 ClsLog 這個類別的型態。

以上是 Autofac 如何利用 Autofac.Integration.Mvc 組件來實行對 .NET MVC 的 Controller 建構子參數作 DI,希望能夠協助幫助,想要知道真相是如何運作的人,基礎的入門重點。 

Event-driven 運用 - 以Queue來實務模擬運作
Autofac 套件之如何快速擴充客製註冊方法 - 以變更RegisterDecorator為例

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/04/25, 週四

Captcha 圖像