在上一篇:IoC基本概念介紹介紹了IoC和DI的概念。在最後提到了,如果沒有一個東西幫我們管理DI,那麼其實整個的彈性設計還是無法彈性起來。
因此在這一篇,我們就來看一下其中一個比較常用的DI Container:Autofac。
DI Container的選擇
其實有很多種DI Container,它們的運作邏輯都差不多,因此假設不希望在自己的專案裡面使用Autofac,完全可以換一個用的習慣的DI Container。
之前在第一篇提到的Fail-Tracker(Github),它裏面使用的就是Structuremap這個DI Container。
如果還沒有選好要用的DI Container,又想要貨比三家,可以參考這篇部落格 IoC Container Benchmark - Performance comparison 看看針對比較常見的.Net DI Container做效能和功能的比較。
Autofac介紹
Autofac
- 官網:http://autofac.org/
- 文件:http://autofac.readthedocs.org/en/latest/
- Nuget上面和它有關的package:Nuget網頁搜索
- Autofac nuget 安裝指令:Install-Package Autofac
- Autofac 和asp .net mvc 5 整合的nuget 安裝指令:Install-Package Autofac.Mvc5
- 其他備註:Autofac不止適合用在Mvc裡面,基本上所有類型的.Net他都有對應的整合Helper(就像上面那個就是針對mvc 5的整合helper)。
Autofac 基本概念介紹
基本上來說使用Autofac的流程就是:
第一步,建立ContainerBuilder
在第一步就是建立一個ContainerBuilder的物件。要建立DI Container,你當然需要告訴他什麽東西配對什麽,因此,這個物件會記錄你註冊進去的Service(服務)和Component(元件)- 等一下在有比較詳細介紹這兩個的意思,最後都註冊完了,就建立出一個DI Container。
第二步,註冊服務
第二步就是註冊服務。在Autofac裡面基本上最長看到的應該就是Service和Component:
- Component:要註冊到Container的類別。Component基本上就是你和DI Container要東西的時候,他會new給你的類別
- Service:Service就是Component會提供的服務。基本上會是interface(當然,不一定是要interface)。
在註冊服務這一邊,Autofac有提供所謂的module,也就是比較複雜或可重複使用的服務註冊可以把它包成一個module,這樣以後註冊起來很方便(Autofac和Mvc的結合也是用了 Module,方便註冊Mvc相關)
在註冊服務這一方面,Autofac提供了很多種的註冊方式,可以由寫C#來註冊,也可以由讀xml來設定註冊,因此非常彈性。
在註冊這一塊其實很多細節,詳細可以參考:Registering Component
第三步,建立Container
第三步就是當我們把要用的service和component都註冊完成了之後,就會呼叫ContainerBuilder.Build()。這個的東西就是我們的DI Container。
最後一步,取得我們要的Component
最後,有了Container,我們就可以透過Container,來取得我們需要的component。
這個在文件裡面稱之為Resolving,相關的使用方法可以參考文件的Resolving Service。
Resolving我不會提太多,因為基本上多我們來說是無縫的和Mvc整合,我們不需要自己手動Resolve。因此,之後有需要請參考文件。
Autofac 使用範例
下面的範例是我從官網抄下來,裡面的注解介紹了每一個部份:
// 第一步,建立ContainerBuilder
var builder = new ContainerBuilder();
// 開始 第二步,註冊service
// 註冊ConsoleLogger這個class為ILogger Service的Component
builder.RegisterType<ConsoleLogger>.As<ILogger>();
// 如果寫法是:builder.RegisterType<ConsoleLogger>();
// 那麼就是ConsoleLogger這個class為ConsoleLogger Service的Component
// 註冊自己實例化出來的物件
// 上面是只註冊class type(因此,用到的時候是autofac幫你new出來),這邊是直接用這個object
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
// 用lambda 註冊會更有彈性,因為傳進來的c是container的instance,因此可以用c來做一些複雜的東西。
builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>();
// 假設不想要一個一個註冊,可以用scan的方式。
// 下面scan一個assembly所有的type,當那個type的名字最後結尾是Repository的時候,
// 把它註冊的service設為這個class的interface
builder.RegisterAssemblyTypes(myAssembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
//結束 第二步
// 第三步,註冊都完成了,建立自己的container
var container = builder.Build();
// 第四部,從container取得對應的component。
// 這邊用using包起來,因為出了這個scope,一切Resolve出來的都會被釋放掉。
// 這部份在我們整個系列碰到並不多,因為不建議自己每一個這樣取出來,
// 而是用深度整合的方式來讓一切像自動發生。
// 詳細之後就會比較清楚
using(var scope = container.BeginLifetimeScope())
{
var reader = container.Resolve<IConfigReader>();
}
結語
如果從來沒有使用過DI Container,看到這邊可能還是覺得很抽象,不確定怎麼用。不用擔心,之後我們在開發框架的時候會使用到,到時候在回來比照前面這些內容,相信因該會給一個不錯的起始點。
Autofac其實細部有很多內容,我這邊只碰到了最基礎的部份,希望透過這一篇能夠打開DI Container和Autofac的一些學習曲綫,給予一個好的起始點,之後要查找問題能夠更容易一些。
本來這一篇會介紹到Autofac如何和Asp .net Mvc整合,但在寫下去怕太長,因此Mvc的部份就留到下一次在講。
Reference
再次總結一下相關資源:
- 第一個一定要再次介紹官網,因為裡面的文件很詳細(只不過它是英文)官網 、文件
- 黑大曾經有寫過一些Autofac相關:Autofac筆記 1、 其他Autofac相關
- DI Container 的比較和評測:IoC Container Benchmark - Performance comparison