主要內容
1.為什麼要IOC
2.什麼是Castle IOC容器
3.快速入門示例
4.幾個重要的概念
一,為什麼要IOC
IOC(控制反轉或者叫依賴注入)Martin Fowler大師在他的文章中已經講解的非常精彩了,這裡實在不敢班門弄斧,只好簡單地解釋幾句。我們使用抽象接口來隔離使用者和具體實現之間的依賴關系,但是不管再怎麼抽象,最終還是要創建具體實現類的實例,這種創建具體實現類的實例對象就會造成對於具體實現的依賴,為了消除這種創建依賴性,需要把依賴移出到程序的外部(比如配置文件)。使用依賴注入後,這些類完全是基於抽象接口編寫而成的,所以可以最大限度地適應需求的變化。依賴注入的形式有三種,分別為構造子注入(Constructor Injection)、設值方法注入(Setter Injection)和接口注入(Interface Injection)。
二.什麼是Castle IOC容器
Windsor是Castle 的一個IOC容器。它構建於MicroKernel之上,功能非常之強大,能檢測類並了解使用這些類時需要什麼參數,檢測類型和類型之間工作依賴性,並提供服務或者發生錯誤時提供預警的機制。
三.快速入門示例
現在假如我們有這樣一個需求,開發一個日志組件,把日志信息輸出到文本文件,同時對輸出的信息進行格式化,以示意性的代碼來實現。
1.新建一個C#工程,添加對以下Dll的引用
Castle.DynamicProxy.dll
Castle.MicroKernel.dll
Castle.Model.dll
Castle.Windsor.dll
2.編寫服務
既然是日志組件,我們先添加兩個接口分別為ILog和ILogFormatter,這樣的接口我們一般叫做服務,即實現了某種服務的接口(後面會講到)。
/**//// <summary>
/// 編寫:Terrylee
/// 出處:http://terrylee.cnblogs.com
/// </summary>
public interface ILog
{
void Write(string MsgStr);
}
/**//// <summary>
/// 編寫:Terrylee
/// 出處:http://terrylee.cnblogs.com
/// </summary>
public interface ILogFormatter
{
string Format(string MsgStr);
}
3.編寫組件
僅僅有接口還不行,還需要實現了上面兩個接口的具體實現類,這些類我們把它叫做組件。
/**//// <summary>
/// 編寫:Terrylee
/// 出處:http://terrylee.cnblogs.com
/// </summary>
public class TextFileLog : ILog
{
private string _target;
private ILogFormatter _format;
public TextFileLog(string target,ILogFormatter format)
{
this._target = target;
this._format = format;
}
public void Write(string MsgStr)
{
string _MsgStr = _format.Format(MsgStr);
_MsgStr += _target;
//Output Message
Console.WriteLine("Output "+_MsgStr);
}
}
/**//// <summary>
/// 編寫:Terrylee
/// 出處:http://terrylee.cnblogs.com
/// </summary>
public class TextFormatter : ILogFormatter
{
public TextFormatter()
{
}
public string Format(string MsgStr)
{
return "[" + MsgStr + "]";
}
}
4.編寫配置文件
編寫配置文件,由於TextFileLog構造函數中除了需要一個ILogFormatter的實例之外,還需要指定信息的輸出的文本文件名,所以編寫一個配置文件來指定,這個也可以放在應用程序配置文件中(Web.config或者App.config)。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<components>
<component id="txtLog">
<parameters>
<target>log.txt</target>
</parameters>
</component>
</components>
</configuration>
5.使用Castle IOC容器
前面的幾步僅僅是為我們Castle IOC做准備,下面就是正式使用了。使用Castle IOC容器非常簡單,基本上分為建立容器,加入組件,獲取組件,使用組件幾個步驟。
/**//// <summary>
/// 編寫:Terrylee
/// 出處:http://terrylee.cnblogs.com
/// </summary>
public class App
{
public static void Main()
{
//建立容器
IWindsorContainer container = new WindsorContainer( new XmlInterpreter("../../BasicUsage.xml") );
//加入組件
container.AddComponent( "txtLog",
typeof(ILog), typeof(TextFileLog) );
container.AddComponent( "format",
typeof(ILogFormatter), typeof(TextFormatter) );
//獲取組件
ILog log = (ILog) container["txtLog"];
//使用組件
log.Write("First Castle IOC Demo");
Console.ReadLine();
}
}
簡單的描述一下:
第一步:注冊了一個Windsor容器;
第二步:向容器中注冊ILog服務,並告訴容器TextFileLog實現了這個服務,這裡還設置了一個key的參數,後面可以通過這個參數來獲取這個服務,注冊ILog時容器會發現這個服務依賴於其他的服務,它會自動去尋找,如果找不到這樣的服務,則會拋出一個異常;
第三步:向容器中注冊ILogFormatter並告知TextFormatter實現了它;
第四步:容器發現類的構造函數還需要另外一個參數target,這裡指定了到BasicUsage.xml中去查找。
運行程序,可以看到輸出的結果:
Output[FirstCastleIOCDemo]log.txt
怎麼樣?夠簡單的吧。可以看到整個過程非常的簡單,代碼也非常優雅,我們並沒有使用new關鍵字創建一個具體實現類的實例,至此,一個簡單的使用Castle IOC的過程就完成了。下面我們來理解一下其中幾個重要的概念。
四.幾個重要的概念
1.服務
服務是一個個的接口,接口約定了服務,從而使隨意替換服務的實現對使用接口服務的代碼沒有任何的影響。像我們上面例子中的ILog,ILogFormatter都是一個個服務,我們在這個例子中支實現了一個文本文件的日志記錄,如果你要是實現數據庫記錄的日志記錄,都必須要遵守ILog這個接口。
2.組件
簡單來說組件是一個可重用的程序單元,它實現了某個接口,並僅僅只實現了這一個良好的接口。也就是說,組件是實現了某個服務接口的類。像上例中的TextFileLog,TextFormatter都是組件
3.自動裝配
在上面的例子中,大家可能都已經注意到了,TextFileLog依賴於TextFormatter,我們卻沒有在配置文件中指定它們之間的依賴關系,這就是Castle IOC聰明的一個地方,它能夠自動管理組件之間的依賴關系,而無需編寫特定的xml config來配置,即自動裝配的意思。
Castle IOC容器快速入門指南就到這兒,歡迎大家多多指教,後續文章我會詳細的去寫Castle IOC及其Facility。