通常IOC实现的步骤为-->建立容器-->加入组件-->获取组件-->使用组件.
1.建立容器
建立容器也就是IWindsorContainer.接着我门要向容器中注册服务,并告诉容器所注册的服务由那一个类来实现他.通常建立容器我们可以用以下定义来实现:
1
IWindsorContainer container
=
new
WindsorContainer();
2.加入组件
向建立好的容器里加入组件,直接调用容器的 AddComponent()来完成.比如现在有一个写日志的接口ILog,实现这个服务的组件是TextLog,那我门可以通过如下方法把该组件加入到容器:
1
container.AddComponent(
"
txtLog
"
,
typeof
(ILog),
typeof
(TextLog));
3.获取组件
获取组件可以直接通过加入组件的时候使用的key来获取,返回的是一个 IWindsorContainer,这里需要一个强制转换.
1
ILog log
=
(ILog)container[
"
txtLog
"
];
4.使用组件
1
//
把当前时间写入到日志文件去
2 log.Write(DateTime.Now.ToShortDateString());
上面就是一个IOC容器的工作过程,从创建容器--加入组件--获取组件--使用组件.下面我看来看看一个小实例,也就是我在学习IOC的时候结合网上的资源自己小试牛刀瞎写的.
2 log.Write(DateTime.Now.ToShortDateString());
-------------------------------------------------------------------------------------------------------------
ILog接口(服务)的定义:
1
using
System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace 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
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace 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组件的定义:
Code
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}
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
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,可将日志格式化为一定的格式输出,定义如下:
Code
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 /**//// <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}
Code
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 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}
到这里,来写个测试方法测试看看.
1
namespace
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}
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>
6 public TextFileLog( string target, ILogFormat format)
7 {
8 this._target = target;
9 this._format = format;
10}
在前面向容器中注册ILog服务的时候,告诉容器TextFileLog实现了这个服务,这里还设置了一个key的参数,后面可以通过这个参数来获取这个服务,注册ILog时容器会发现这个服务依赖于其他的服务,它会自动去寻找,如果找不到这样的服务,则会抛出一个异常.2/// 构造方法
3/// </summary>
4/// <param name="target">标识</param>
5/// <param name="format">提供格式化服务的接口</param>
6 public TextFileLog( string target, ILogFormat format)
7 {
8 this._target = target;
9 this._format = format;
10}
到这里,一个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 >
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,详细如下:
1
namespace 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就学与此,笔记也记于此.小弟是刚开始着手学习这门技术,望园里前辈别见笑,我不赶搬门弄虎的写什么文章,这篇文章只是我的一篇学习笔记罢了.
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 }
本文示例代码下载
想学习Castle的朋友我建议去看看李会军老师的文章,本文部分内容也是来自他的blog.
Castle 开发系列文章