1.什么是IOC
IOC是一种设计模式,全程控制翻转或叫依赖注入。更详细介绍见http://martinfowler.com/articles/injection.html
2.为什么用IOC
我们通常使用抽象接口来隔离使用者与具体实现之间的依赖关系。但是不管怎么抽象接口,最终接口都必须要创建具体的实现类实例。这种创建实对象的操作导致了对于具体实现的依赖。为了消除这种依赖,我们需要把依赖移除到程序外部。引入了IOC容器后,这些类完全基于抽象接口编写而成。一般有三种形式,1.构造函数注入,2.属性注入,3.接口注入
3.一个简单的IOC实例
下面通过Castle IOC容器做一个简单的示例说明
3.1 Castle IOC
Windsor是Castle的一个IOC容器,构建于MicroKernel,能检测并了解使用这些类时需要什么参数,检测类型和类型之间的工作依赖性。
3.2 简单实例
假设我们有一个开发日志组件需求,把日志信息输出到文本文件,同时对输出的信息进行格式化。
step1:新建工程添加dll引用
Castle.DynamicProxy.dll
Castle.MicroKernel.dll
Castle.Model.dll
Castle.Windsor.dll
step2:编写服务
日志组件,我们添加两个接口ILog和ILogFormatter,这样的接口也叫做服务(实现了某种服务的接口)
public interface ILog { void Write(string MsgStr); }
public interface ILogFormatter { string Format(string MsgStr); }
Step3:编写组件(接口实现)
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; Console.WriteLine("Output "+_MsgStr); } }
public class TextFormatter : ILogFormatter { public TextFormatter() { } public string Format(string MsgStr) { return "[" + MsgStr + "]"; } }
Step3:编写配置文件
在TextFileLog构造函数中需要ILogFormatter实例外,还需要指定信息的输出文本名,这里我们编写一个配置文件来指定
<?xml version="1.0" encoding="utf-8" ?> <configuration> <components> <component id="txtLog"> <parameters> <target>log.txt</target> </parameters> </component> </components> </configuration>
Step4:使用IOC容器
前面都是小菜,下面开始正式使用了。建立容器,加入组件,获取组件,使用组件。
public class App { public static void Main() { //建立容器 IWindsorContainer container = new WindsorContainer(); //加入组件 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参数,后面直接通过key来获取服务。
- 注册ILog时容器会发现这个服务依赖于其他服务,自动寻找。
- 向容器中注册ILogFormatter并告知TextFormatter实现了它。
- 容器发现类的构造函数还需要target参数,指定去xml中查找。
参考资料
Castle的官方网站http://www.castleproject.org