開始
首先我們根據(jù)官方的文檔做一個例子矾屯,來體驗一下:
首先安裝Autofac包
- 按照控制反轉(zhuǎn)(IoC)的思想構(gòu)建你的應(yīng)用程序
- 添加Autofac引用
- 在
application
啟動代碼里… - 創(chuàng)建
ContainerBuilder
對象 - 注冊組件
- Build容器并且保存以備用
- 在程序執(zhí)行階段
- 從容器創(chuàng)建一個作用域
- 在作用域里獲取組件的實例
應(yīng)用程序構(gòu)建
在我們的例子里腹暖,我們將定義一個類來輸出當前的日期榛泛。當然饥漫,我們不希望和Console
綁定因為我們想在控制臺不可用的情況依然可以測試這個類眯娱。
同樣惠桃,輸入日期的方法被定義成抽象的,這樣的話如果我們想新增一個輸出明天日期的方法就可以直接重載邑飒。
我們先定義一段代碼:
using System;
namespace DemoApp
{
// 這個接口幫助我們從Console類解耦"輸出"方法
// 我們不需要關(guān)心怎樣輸出,只要知道能輸出即可
public interface IOutput
{
void Write(string content);
}
// 這里IOutput接口的實現(xiàn)完成向控制臺的輸出级乐。
// 技術(shù)上講疙咸,我們可以實現(xiàn)IOutput接口完成Debug或者Trace或者
// 其他的輸出方式
public class ConsoleOutput : IOutput
{
public void Write(string content)
{
Console.WriteLine(content);
}
}
// 這個接口解耦實際輸出日期的接口。
// 像IOutput一樣风科,這個處理在后面的接口里抽象化
public interface IDateWriter
{
void WriteDate();
}
// ToadyWriter將上述兩個接口進行組合
// 注意這里的構(gòu)造函數(shù)參數(shù)是IOutput類型
// 這樣這個writer的輸出由IOutput的實現(xiàn)決定
// 更進一步說撒轮,他實現(xiàn)了WriteDate輸出今天的日期
// 你可以再定義一個輸出不同格式或者不同日期的方法
public class TodayWriter : IDateWriter
{
private IOutput _output;
public TodayWriter(IOutput output)
{
this._output = output;
}
public void WriteDate()
{
this._output.Write(DateTime.Today.ToShortDateString());
}
}
}
應(yīng)用程序啟動
在應(yīng)用程序啟動過程中,首先要創(chuàng)建一個ContainerBuilder
并且用它注冊你的組件贼穆。組件是一個表達式, .NET類型或者其他的一段暴露一個或者多個服務(wù)的代碼并且可以用在其他的依賴里题山。
簡單來說,就像下面的例子所述故痊,定義一個實現(xiàn)某個接口的.NET類型
public class SomeType : IService
{
}
你可以通過下面兩種方法之一來定位這個類型
- 指定類型本身顶瞳,
SomeType
- 指定接口,一個
IService
在這個例子里愕秫,這個組件是SomeType
慨菱,他暴露的服務(wù)是SomeType
和IService
.
在Autofac里,你應(yīng)當用一個ContainerBuilder
來注冊他們戴甩,如下:
// 創(chuàng)建你的builder
var builder = new ContainerBuilder();
// 通常你只關(guān)心這個接口的一個實現(xiàn)
builder.RegisterType<SomeType>().As<IService>();
// 當然抡柿,如果你想要全部的服務(wù)(不常用),可以這么寫:
builder.RegisterType<SomeType>().AsSelf().As<IService>();
在我們的例子里等恐,我們要注冊所有的組件(類)并且獲取他們的服務(wù)(接口)洲劣,這樣這些對象連接起來會更方便
我們還要保存這個容器,這樣我們可以在后面用來解析這些類型
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();
}
public static void WriteDate()
{
// 創(chuàng)建作用域囱稽,解析IDateWriter,使用二跋,然后釋放
using (var scope = Container.BeginLifetimeScope())
{
var writer = scope.Resolve<IDateWriter>();
writer.WriteDate();
}
}
}
}
當你運行你的程序時…
- WriteDate方法要求Autofac提供
IDateWriter
. - Autofac發(fā)現(xiàn)
IDateWriter
映射到TodayWriter
所以創(chuàng)建了一個TodayWriter
對象 - Autofac發(fā)現(xiàn)
TodayWriter
構(gòu)造函數(shù)需要IOutput
- Autofac發(fā)現(xiàn)
IOutput
映射到ConsoleOutput
战惊,所以創(chuàng)建一個新的ConsoleOutput
的實例 - Autofac使用
ConsoleOutput
實例完成TodayWriter
的創(chuàng)建 - Autofac返回一個完整的
TodayWriter
對象給”WriteDate”來消費
最后,如果你希望你的應(yīng)用輸出一個不同的日期扎即,你可以實現(xiàn)另外一個IDateWriter
然后再app啟動的時候改變一下注冊過程吞获。你不需要修改任何其他的類。耶谚鄙,控制反轉(zhuǎn)了各拷!
注意:通常來說,服務(wù)定位大多都考慮了反面模式(參考) http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx闷营。就是說烤黍,在你的代碼里到處分散的手動創(chuàng)建作用域不是最佳的實現(xiàn)方式知市。使用Autofac整合庫以后,你通常不需要做本例中的處理速蕊。相反的嫂丙,對象很少在應(yīng)用程序的”頂級”位置解析或者在手動解析。當然规哲,怎么設(shè)計你的app是由你自己決定的跟啤。
更進一步
這個例子告訴你怎么使用Autofac,但是你還需要了解更多的內(nèi)容
- 查看Autofac整合庫列表來了解如何整合Autofac到你的應(yīng)用程序里
- 學(xué)習(xí)注冊組件的方法提高代碼靈活性
- 學(xué)習(xí)Autofac配置選項更好的管理你的組件注冊