Windsor是Castle 的一個IOC容器。它構建於MicroKernel之上,功能非常之強大,能檢測類並了解使用這些類時需要什麼參數,檢測類型和類型之間工作依賴性,並提供服務或者發生錯誤時提供預警的機制。
通常IOC實現的步驟為-->建立容器-->加入組件-->獲取組件-->使用組件.
1.建立容器
建立容器也就是IWindsorContainer.接著我門要向容器中注冊服務,並告訴容器所注冊的服務由那一個類來實現他.通常建立容器我們可以用以下定義來實現:
1IWindsorContainer container = new WindsorContainer();
2.加入組件
向建立好的容器裡加入組件,直接調用容器的AddComponent()來完成.比如現在有一個寫日志的接口ILog,實現這個服務的組件是TextLog,那我門可以通過如下方法把該組件加入到容器:
1container.AddComponent("txtLog", typeof(ILog), typeof(TextLog));
3.獲取組件
獲取組件可以直接通過加入組件的時候使用的key來獲取,返回的是一個IWindsorContainer,這裡需要一個強制轉換.
1ILog log = (ILog)container["txtLog"];
4.使用組件
1//把當前時間寫入到日志文件去
2log.Write(DateTime.Now.ToShortDateString()); 上面就是一個IOC容器的工作過程,從創建容器--加入組件--獲取組件--使用組件.下面我看來看看一個小實例,也就是我在學習IOC的時候結合網上的資源自己小試牛刀瞎寫的.
-------------------------------------------------------------------------------------------------------------
ILog接口(服務)的定義:
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace IOCDayOne
6{
7 /**//// <summary>
8 /// 日志服務
9 /// </summary>
10 public interface ILog
11 {
12 /**//// <summary>
13 /// 寫日志方法
14 /// </summary>
15 /// <param name="msgStr">日志內容</param>
16 void Write(string msgStr);
17 }
18}
19
TextLog組件的定義:
1namespace IOCDayOne
2{
3 /**//// <summary>
4 /// ILog服務的組件
5 /// </summary>
6 public class TextFileLog:ILog
7 {
8 private string _target; //私有成員
9 private ILogFormat _format; //ILogFormat一內聚的方式存在
10
11 /**//// <summary>
12 /// 構造方法
13 /// </summary>
14 /// <param name="target">標識</param>
15 /// <param name="format">提供格式化服務的接口</param>
16 public TextFileLog(string target, ILogFormat format)
17 {
18 this._target = target;
19 this._format = format;
20 }
21
22 /**//// <summary>
23 /// 寫日志的實現方法
24 /// </summary>
25 /// <param name="msgStr">日志內容</param>
26 public void Write(string msgStr)
27 {
28 string str = _format.Format(msgStr); //格式化日志
29 str += _target; //日志內容為格式化後的字符+類構造時傳入的標識參數
30
31 //下面將日志記錄到文本文件
32 FileStream fs = new FileStream(this._target, FileMode.Append);
33 StreamWriter sw = new StreamWriter(fs, Encoding.Default);
34 sw.WriteLine("Log:-->" + str);
35 sw.Close();
36 }
37 }
38}
XML配置文件的定義(指定將日志記錄到C:\Log.txt),TextLog組件需要存儲路徑的參數,我們在建立IOC容器的時候指定容器到這個配置文件中來找"target":
1<?xml version="1.0" encoding="utf-8" ?> 2<configuration> 3 <components> 4 <component id="txtLog"> 5 <parameters> 6 <target>C:\Log.txt</target> 7 </parameters> 8 </component> 9 </components> 10</configuration> 11
出此之外還有一個格式化日志的服務IlogFormat,可將日志格式化為一定的格式輸出,定義如下:
1namespace IOCDayOne
2{
3 /**//// <summary>
4 /// 格式化日志服務接口
5 /// </summary>
6 public interface ILogFormat
7 {
8 /**//// <summary>
9 /// 格式化日志方法
10 /// </summary>
11 /// <param name="msgStr">日志內容</param>
12 /// <returns></returns>
13 string Format(string msgStr);
14 }
15}
實現ILogFormat服務的組件定義為:
1namespace IOCDayOne
2{
3 public class TextFormat:ILogFormat
4 {
5 /**//// <summary>
6 /// 格式化日志內容
7 /// </summary>
8 /// <param name="msgStr">日志內容</param>
9 /// <returns></returns>
10 public string Format(string msgStr)
11 {
12 return "On:" + msgStr;
13 }
14 }
15}
到這裡,來寫個測試方法測試看看.
1namespace IOCDayOne
2{
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //建立容器
8 IWindsorContainer container = new WindsorContainer(new XmlInterpreter("http://www.cnblogs.com/Config/ConfigBase.xml"));
9 //加入組件
10 container.AddComponent("txtLog", typeof(ILog), typeof(TextFileLog));
11 container.AddComponent("format", typeof(ILogFormat), typeof(TextFormat));
12 //獲取組件
13 ILog log = (ILog)container["txtLog"];
14 //使用組件
15 log.Write(DateTime.Now.ToShortDateString());
16 }
17 }
18}
測試輸出的結果為:
Log:-->On:2008-4-3C:\Log.txt
上面的main()中可以看書,在使用組件的時候只傳遞了一個參數(日志內容),而實現ILog服務的組件的構造方法是需要兩個參數,
1/**//// <summary>
2/// 構造方法
3/// </summary>
4/// <param name="target">標識</param>
5/// <param name="format">提供格式化服務的接口</param>
6public TextFileLog(string target, ILogFormat format)
7{
8 this._target = target;
9 this._format = format;
10}
在前面向容器中注冊ILog服務的時候,告訴容器TextFileLog實現了這個服務,這裡還設置了一個key的參數,後面可以通過這個參數來獲取這個服務,注冊ILog時容器會發現這個服務依賴於其他的服務,它會自動去尋找,如果找不到這樣的服務,則會拋出一個異常.
到這裡,一個IOC的完整實例就完成了.其實還有另外一種方式實現.詳細見下面.
-------------------------------------------------------------------------------------------------------------
上面是通過把配置寫到XML的,而組件與服務是直接通過容器的加入組件來完成匹配.這樣顯然是不夠靈活的,一單需求發生了變化,實現ILog服務的組件不在是TextFileLog的時候又該怎麼處理呢?我們又去修改加入組件時的程序代碼來實現,這樣是可以達到需求的,但是這樣做很明顯不夠靈活.那怎麼做才能讓服務去調用具體的實現組件修改方便呢?另一種方式是通過配置文件(App.config/Web.config)來實現.
下面是針對上面這個實例定義的App.config配置:
1<?xml version="1.0" encoding="utf-8" ?> 2<configuration> 3 <configSections> 4 <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor"/> 5 </configSections> 6 <castle> 7 <components> 8 <component id="txtLog" service="IOCDayOne.ILog,IOCDayOne" type="IOCDayOne.TextFileLog,IOCDayOne"> 9 <parameters> 10 <target>C:\Log.txt</target> 11 </parameters> 12 </component> 13 <component id="format" service="IOCDayOne.ILogFormat,IOCDayOne" type="IOCDayOne.TextFormat,IOCDayOne"> 14 <paramters> 15 <target>DayOne</target> 16 </paramters> 17 </component> 18 </components> 19 </castle> 20</configuration>
這時,測試方法就需要改動下了,通過配置文件來完成IOC,詳細如下:
1namespace IOCDayOne
2{
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //建立容器,並通過配置文件最動加入組件
8 IKernel kernel;
9 Castle.Core.Resource.ConfigResource source = new Castle.Core.Resource.ConfigResource();
10 XmlInterpreter interpreter = new XmlInterpreter(source);
11 WindsorContainer windsor = new WindsorContainer(interpreter);
12 kernel = windsor.Kernel;
13
14 //獲取組件
15 ILog log = (ILog)kernel["txtLog"];
16
17 //使用組件
18 log.Write(DateTime.Now.ToShortDateString());
19 }
20 }
21}
今天的IOC就學與此,筆記也記於此.小弟是剛開始著手學習這門技術,望園裡前輩別見笑,我不趕搬門弄虎的寫什麼文章,這篇文章只是我的一篇學習筆記罷了.
本文配套源碼