Autofac官方文件(一)【開始】
將Autofac整合到您的應用程式的基本模式是:
記住控制反轉(IoC)的結構。
新增Autofac引用。
在應用程式啟動...
建立一個ContainerBuilder。
註冊元件。
構建容器並將其儲存以備後用。
在執行應用程式時
從容器建立一個生命週期範圍。
使用生命週期作用域來解析元件的例項。
本入門指南將引導您完成簡單的控制檯應用程式的這些步驟。 一旦您掌握了基本知識,您可以檢視Wiki的其他部分,以獲取有關WCF,ASP.NET和其他應用程式型別的更高階用法和整合資訊。
構建應用程式
控制反轉背後的想法,而不是把你的應用程式中的類繫結在一起,讓類“新建”它們的依賴關係,你可以切換它,所以在構造類的時候依賴關係被傳入。Martin Fowler
依賴注入/控制反轉
。
對於我們的示例應用程式,我們將定義一個將當前日期寫入的類。 但是,我們不希望它繫結到控制檯,因為我們希望能夠稍後測試該類,或者在控制檯不可用的地方使用它。
我們也會盡量讓寫日期的機制被抽象出來,所以如果我們稍後想換一個寫明天日期的版本的話,那將是一個很好的選擇。
我們會做這樣的事情:
using System;
namespace DemoApp
{
//這個介面有助於從Console類中去除“寫入輸出”的概念。我們並不真正“關心”寫操作是如何發生的,只是我們可以寫。
public interface IOutput
{
void Write(string content);
}
//IOutput介面的這種實現實際上是我們如何寫入控制檯。 從技術上講,我們也可以實現IOutput來寫入除錯或跟蹤...或其他任何地方。
public class ConsoleOutput : IOutput
{
public void Write(string content)
{
Console.WriteLine(content);
}
}
//這個介面把執行寫操作的實際機制的寫日期的概念分離出來。 和IOutput一樣,這個過程在一個介面後面被抽象出來。
public interface IDateWriter
{
void WriteDate();
}
//這個TodayWriter是所有匯聚一起的地方。
//請注意,它需要一個型別為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
註冊這樣的東西:
// 建立你的構建者
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方法是我們將使用依賴注入的地方。 我們將定義一下。
WriteDate();
}
}
}
現在我們有一個包含所有元件註冊的容器,並且提供了正確的服務。讓我們來利用它。
應用程式執行
在執行應用程式時,您需要使用您註冊的元件。你可以通過解決他們的生命週期域來做到這一點。
容器本身是一個有生命週期範圍,你可以在技術上直接從容器中解決問題。但不建議直接從容器中解析。
在解析元件時,根據您定義的例項範圍,將建立物件的新例項。 (解析一個元件大致等同於呼叫“new”來例項化一個類,這實際上是真正的簡化了它,但是從類比的角度來看它沒問題)。一些元件可能需要處理(就像它們實現IDisposable一樣) - Autofac可以處理在處置壽命範圍時為您配置這些元件。
但是,容器在您的應用程式的整個生命週期中都存在。如果你直接從容器中解決了很多東西,最終可能會有很多東西在等待處理。這不好(你可能會看到一個“記憶體洩漏”)。
相反,從容器中建立一個子生命週期範圍並從中解決。當你完成解決元件,處理子範圍,一切都為你清理。
(當你使用Autofac整合庫時,這個子範圍的建立基本上是為你完成的,所以你不必考慮它。)
對於我們的示例應用程式,我們將實現“WriteDate”方法來從作用域獲取寫入器,並在完成時處理作用域。
namespace DemoApp
{
public class Program
{
private static IContainer Container { get; set; }
static void Main(string[] args)
{
// 你之前看到的東西
}
public static void WriteDate()
{
//建立作用域,解析IDateWriter,使用它,然後處理作用域。
using (var scope = Container.BeginLifetimeScope())
{
var writer = scope.Resolve<IDateWriter>();
writer.WriteDate();
}
}
}
}
Now when you run your program…
現在當你執行你的程式…
“WriteDate”方法向Autofac請求IDateWriter。
Autofac看到IDateWriter對映到TodayWriter,所以開始建立TodayWriter。
Autofac認為TodayWriter在其建構函式中需要一個IOutput。
Autofac將IOutput對映到ConsoleOutput,以建立一個新的ConsoleOutput例項。
Autofac使用新的ConsoleOutput例項來完成構建TodayWriter。
Autofac返回完全構建的`“WriteDate”`TodayWriter給使用消費者。
之後,如果您希望應用程式寫入不同的日期,則可以實現不同的IDateWriter,然後在應用程式啟動時更改註冊。你不必改變任何其他類。很好,控制反轉!
注意:一般來說,服務定位在很大程度上被認為是反模式(見文章)。也就是說,在任何地方手動建立作用域,並通過程式碼來使用容器不一定是最好的方法。使用Autofac整合庫,您通常不必執行上面示例應用程式中的操作。相反,事情從應用程式的中央“頂級”位置解決,而手動解決方案很少見。當然,你如何設計你的應用程式取決於你。
進一步
示例應用程式給你一個如何使用Autofac的想法,但還有很多你可以做的。
檢視整合庫列表,瞭解如何將Autofac與您的應用程式整合。
瞭解如何註冊增加靈活性的元件。
瞭解Autofac配置選項,以便您更好地管理元件註冊。