【寫在前面】嘗試作完一件工做以外自我以爲有意義的一件事,那就從翻譯Autofac的幫助文檔吧。html
將Autofac集成你的應用程序的步驟一般很簡單,通常是:ui
本篇將經過入門指南實現一個簡單的Console應用程序,一旦有了基礎,後續能夠延伸集成WCF、ASP.NET等等。this
先簡單解釋一下IOC(控制反轉)。
一般狀況下,類A若須要類B的一些功能,則在類A中須要經過「new」操做來完成建立和使用功能,這樣在代碼層面就固定住了類A和類B之間的相互依賴關係。這樣的「依賴」,在後續的重構或修改時,影響面很大。
而IOC(控制反轉)的思惟,則是取消,由類A來建立類B,變動爲在執行期間,由IOC容器來根據須要和約定自動建立類B來給類A使用。spa
Martin Fowler有一篇著名的文章,解釋何謂IOC,能夠點擊「連接」查看。.net
在本篇的示例中,咱們將定義一個類,這個類能夠輸出一些數據;但咱們不想和Console綁定住,由於咱們並不能肯定在實際使用過程當中Console是否真的可用。翻譯
咱們一般能夠這樣實現:設計
using System; namespace DemoApp { // 定義個輸出接口 public interface IOutput { void Write(string content); } // 爲接口實現Console方式的輸出 public class ConsoleOutput : IOutput { public void Write(string content) { Console.WriteLine(content); } } // 定義一個書寫器接口 public interface IDateWriter { void WriteDate(); } // 實現書寫器接口,輸出當前日期,請注意,它依賴於IOutput接口 // 在運行時,才能得到具體的輸出形式 public class TodayWriter : IDateWriter { private IOutput _output; public TodayWriter(IOutput output) { this._output = output; } public void WriteDate() { this._output.Write(DateTime.Today.ToShortDateString()); } } }
至此,咱們已經有了IOC思惟了。下一步,咱們將經過Autofac來實現它。htm
第一步,須要在項目中添加Autofac的引用。建議經過NuGet方式(以下圖),將會自動添加到項目中。對象
Autofac,除了Core以外,還有不少擴展,例如和ASP.NET MVC集成等等。blog
截至目前爲止,Autofac Core最新版本爲4.6.0,對應.net framework 4.5.
在應用程序啓動環節,你須要建立一個ContainerBuilder來註冊組件。
一個組件,能夠是一個表達式,一個.NET類型,又或者能夠是一個或者多個帶依賴項的Service等等。
簡單來講,以下這個實現接口的.NET類,咱們有兩種方式來定義它的類型。
public class SomeType : IService { }
如上的例子,組件就是SomeType,同時也是包括SomeType和IService的兩種形態的服務。
在Autofac,你能夠按照以下方式向ContainerBuilder註冊組件。
// 建立builder. var builder = new ContainerBuilder(); // 一般狀況下,咱們感興趣的是IService: builder.RegisterType<SomeType>().As<IService>(); // 或者,也能夠同時註冊IService和SomeType builder.RegisterType<SomeType>().AsSelf().As<IService>();
對於咱們的示例應用程序,咱們須要註冊全部組件(類),並公開它們的服務(接口),這樣就能夠很好地鏈接起來。
咱們還須要保存Container,以便之後可使用它來解析類型。
using System; using Autofac; namespace DemoApp { public class Program { private static IContainer Container { get; set; } static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType<ConsoleOutput>().As<IOutput>(); builder.RegisterType<TodayWriter>().As<IDateWriter>(); Container = builder.Build(); // WriteDate在執行時,Autofac將自動根據註冊的組件進行裝配並執行. WriteDate(); } } }
如今咱們有一個Container,全部的組件都已註冊,而且它們正在公開適當的服務。讓咱們利用它吧。
在應用程序執行,你須要使用你註冊的組件時,是經過lifetime scope來解析出相應組件實例的。
Container自己也是一個lifetime scope,從技術角度來講,你能夠從Container直接解析出組件,然而並不推薦這樣用。
解析一個組件時,將會根據所定義的實例範圍,建立一個對象的新實例。(解析一個組件大體至關於調用「new」實例化一個類。很簡單的一個類比。),某些組件可能有特殊的Dispose(如組件自己實現了IDisposable)- Autofac能夠在lifetime scope終止時也會自動處理這些組件特殊的Dispose。
Container這個lifetime scope,在應用程序執行時會一直存在。因此,若是用Container來解析全部的組件的話,能夠想象當應用程序終止時,Dispose將是多麼繁忙的景象(全部的組件等待被Dispose),一樣,由於直到最後一刻纔會被Dispose,會更大概率引起「內存不足」這個問題。
因此,推薦從Container建立一個新的lifetime scope來解析組件,在完成相關執行代碼後,lifetime scope連帶着組件便可被釋放。
(一旦你使用了Autofac integration libraries,建立和使用lifetime scope後就能夠徹底忘記它)
對於咱們的示例應用程序,咱們將建立一個lifetime scope,而後解析出writer這個組件,並執行「writedate」方法。
namespace DemoApp { public class Program { private static IContainer Container { get; set; } static void Main(string[] args) { // ...... } public static void WriteDate() { // 建立scope, 解析IDateWriter, // 使用它, 銷燬scope. using (var scope = Container.BeginLifetimeScope()) { var writer = scope.Resolve<IDateWriter>(); writer.WriteDate(); } } } }
如今運行程序…
之後,若是你但願應用程序寫另外一個日期的話,能夠實現一個不一樣的idatewriter而後改變登記程序的啓動。你不須要改變其餘的類。是的,這就是IOC(控制反轉)!
注意:通常來講,Service很大程度上被認爲是一種反模式(看文章)。所以,在你的程序中人工建立scope並使用Container,這種方式不是最好的。使用「Autofac integration libraries」,你一般不須要像示例程序那樣人工建立scope。固然,你如何設計應用程序取決於你本身。
本篇結束。
後述:完整的英文版連接在此:http://autofac.readthedocs.io/en/latest/getting-started/index.html,有部份內容沒有翻譯,也有部份內容自我感受翻譯的並不恰當。若你有意見和建議,可聯繫我。
本博文屬做者原創,首發於www.boxfun.net,除非特別聲明,本做品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。