Autofac官方文件翻譯——(一)Getting Started
立即開始
將Autofac整合到你的應用的基本模式如下:
- 按照控制反轉(IoC)的思想構建你的應用程式
- 新增Autofac引用
- 在application啟動程式碼裡…
- 建立
ContainerBuilder
物件 - 註冊元件
- Build容器並且儲存以備用
- 在程式執行階段
- 從容器建立一個作用域
- 在作用域裡獲取元件的例項
本嚮導通過一個簡單的控制檯應用來介紹上述步驟。一旦你學會了這些步驟,你可以檢視wiki的剩餘部分來了解更多高階用法,通過點選這裡瞭解WCF, ASP.NET, 和其他應用型別的整合方法。
應用程式構建
控制反轉的思想是,在類的建構函式裡傳遞依賴而不是在應用程式裡將這些類綁在一起讓類自己建立他們的依賴。
在我們的例子裡,我們將定義一個類來輸出當前的日期。當然,我們不希望和Console
繫結因為我們想在控制檯不可用的情況依然可以測試這個類。
同樣,輸入日期的方法被定義成抽象的,這樣的話如果我們想新增一個輸出明天日期的方法就可以直接過載。
我們先定義一段程式碼:
using System;
namespace DemoApp
{
// 這個介面幫助我們從Console類解耦"輸出"方法
// 我們不需要關心怎樣輸出,只要知道能輸出即可
public interface IOutput
{
void Write(string content);
}
// 這裡IOutput介面的實現完成向控制檯的輸出。
// 技術上講,我們可以實現IOutput介面完成Debug或者Trace或者
// 其他的輸出方式
public class ConsoleOutput : IOutput
{
public void Write(string content)
{
Console.WriteLine(content);
}
}
// 這個介面解耦實際輸出日期的介面。
// 像IOutput一樣,這個處理在後面的接口裡抽象化
public interface IDateWriter
{
void WriteDate();
}
// ToadyWriter將上述兩個介面進行組合
// 注意這裡的建構函式引數是IOutput型別
// 這樣這個writer的輸出由IOutput的實現決定
// 更進一步說,他實現了WriteDate輸出今天的日期
// 你可以再定義一個輸出不同格式或者不同日期的方法
public class TodayWriter : IDateWriter
{
private IOutput _output;
public TodayWriter(IOutput output)
{
this._output = output;
}
public void WriteDate()
{
this._output.Write(DateTime.Today.ToShortDateString());
}
}
}
現在我們有一個建構函式來設定依賴,我們來新增Autofac進來吧!
新增Autofac引用
第一步是新增Autofac引用到工程裡。在這個例子裡,我們只引用Autofac核心庫。其他應用程式型別可能會用一些額外的Autofac整合庫
最簡單的方法是通過NuGet新增。Autofac程式包裡包含了所需的所有核心功能。
應用程式啟動
在應用程式啟動過程中,首先要建立一個ContainerBuilder
並且用它註冊你的元件。元件是一個表示式, .NET型別或者其他的一段暴露一個或者多個服務的程式碼並且可以用在其他的依賴裡。
簡單來說,就像下面的例子所述,定義一個實現某個介面的.NET型別
public class SomeType : IService
{
}
你可以通過下面兩種方法之一來定位這個型別
- 指定型別本身,SomeType
- 指定介面,一個IService
在這個例子裡,這個元件是SomeType
,他暴露的服務是SomeType
和IService
.
在Autofac裡,你應當用一個ContainerBuilder
來註冊他們,如下:
// 建立你的builder
var builder = new ContainerBuilder();
// 通常你只關心這個介面的一個實現
builder.RegisterType<SomeType>().As<IService>();
// 當然,如果你想要全部的服務(不常用),可以這麼寫:
builder.RegisterType<SomeType>().AsSelf().As<IService>();
在我們的例子裡,我們要註冊所有的元件(類)並且獲取他們的服務(介面),這樣這些物件連線起來會更方便
我們還要儲存這個容器,這樣我們可以在後面用來解析這些型別
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();
}
}
}
現在我們有一個包含了所有元件的容器,而且他們也暴露的相關的服務。我們可以用它們了。
應用程式執行
在應用程式執行階段,你將要用到這些註冊的元件,你可以通過在作用域解析他們來使用。
容器本身是也是一個作用域,而且從技術上講你可以直接從容器解析物件。儘管如此,我們不提倡這麼做。
當你解析了一個元件,一個物件的例項將在你定義的例項範圍內被建立.(解析一個元件基本上跟new一個類是等價的。這的確很簡單,但是從分析角度來說這是OK的)有些元件可能需要釋放(例如實現了IDisposable
介面)- 當作用域釋放的時候可以幫你釋放這些元件。
當然, 容器在你應用程式的整個作用域內都是存在的。如果你直接從container解析了很多物件,在程式終止時可能會有大量的釋放操作將程式掛起。所以不提倡這麼做(而且你可能會遇到“記憶體洩露”的提示)
所以,通過從容器建立一個子作用域範圍來解析物件。當你完成物件解析後,釋放子作用域可以清除該週期建立的一切事物。
(當你使用一些Autofac整合庫)開發時,子作用域已經自動幫你建立了,你無需考慮這些問題。
在這個例子裡,我們將在子作用域裡實現”WriteDate”方法列印日期並且完成後釋放這個作用域
namespace DemoApp
{
public class Program
{
private static IContainer Container { get; set; }
static void Main(string[] args)
{
// ...the stuff you saw earlier...
}
public static void WriteDate()
{
// 建立作用域,解析IDateWriter,使用,然後釋放
using (var scope = Container.BeginLifetimeScope())
{
var writer = scope.Resolve<IDateWriter>();
writer.WriteDate();
}
}
}
}
當你執行你的程式時…
- WriteDate方法要求Autofac提供
IDateWriter
. - Autofac發現
IDateWriter
對映到TodayWriter
所以建立了一個TodayWriter
物件 - Autofac發現
TodayWriter
建構函式需要IOutput
- Autofac發現
IOutput
對映到ConsoleOutput
,所以建立一個新的ConsoleOutput
的例項 - Autofac使用
ConsoleOutput
例項完成TodayWriter
的建立 - Autofac返回一個完整的
TodayWriter
物件給”WriteDate”來消費
最後,如果你希望你的應用輸出一個不同的日期,你可以實現另外一個IDateWriter
然後再app啟動的時候改變一下注冊過程。你不需要修改任何其他的類。耶,控制反轉了!
注意:通常來說,服務定位大多都考慮了反面模式(參考) http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx。就是說,在你的程式碼裡到處分散的手動建立作用域不是最佳的實現方式。使用Autofac整合庫以後,你通常不需要做本例中的處理。相反的,物件很少在應用程式的”頂級”位置解析或者在手動解析。當然,怎麼設計你的app是由你自己決定的。
更進一步
這個例子告訴你怎麼使用Autofac,但是你還需要了解更多的內容
- 檢視Autofac整合庫列表來了解如何整合Autofac到你的應用程式裡
需要幫助?
從原始碼生成
Visual Studio工程的原始碼GitHub。編譯說明在程式碼根目錄的README裡,更多關於工程的資訊參考投稿說明.