控制反转(Inversion of Control,IoC),简言之就是代码的控制器交由系统控制,而不是在代码内部,经过IoC,消除组件或者模块间的直接依赖,使得软件系统的开发更具柔性和扩展性。控制反转的典型应用体如今框架系统的设计上,是框架系统的基本特征,无论是.NET Framework抑或是Java Framework都是创建在控制反转的思想基础之上。html
控制反转不少时候被看作是依赖倒置原则的一个同义词,其概念产生的背景大概来源于框架系统的设计,例如.NET Framework就是一个庞大的框架(Framework)系统。在.NET Framework大平台上能够很容易地构建ASP.NET Web应用、Silverlight应用、Windows Phone应用或者Window Azure Cloud应用。不少时候,基于.NET Framework构建自定义系统的方式就是对.NET Framework自己的扩展,调用框架提供的基础API,扩展自定义的系统功能和行为。然而,无论如何新建或者扩展自定义功能,代码执行的最终控制权仍是回到框架中执行,再交回应用程序。黄忠诚先生曾经在Object Builder Application Block一文中给出一个较为贴切的举例,就是在Window From应用程序中,当Application.Run调用以后,程序的控制权交由Windows Froms Framework上。因此,控制反转更强调控制权的反转,体现了控制流程的依赖倒置,因此从这个意义上来讲,控制反转是依赖倒置的特例。服务器
依赖注入(Dependency Injection,DI),早见于Martin Flower的Inversion of Control Containers and the Dependency Injection pattern一文,其定义可归纳为:框架
客户类依赖于服务类的抽象接口,并在运行时根据上下文环境,由其余组件(例如DI容器)实例化具体的服务类实例,将其注入到客户类的运行时环境,实现客户类与服务类实例之间松散的耦合关系。ide
(1)常见的三种注入方式函数
简单而言,依赖注入的方式被总结为如下三种。ui
首先定义注入的接口:this
public interface IRunnerProviderspa
{.net
void Run(Action action);线程
}
为注入的接口实现不一样环境下的注入提供器,本例的系统是一个后台处理程序提供了运行环境的多种可能,默认状况下将运行于单独的线程,或者经过独立的Windows Service进程运行,那么须要为不一样的状况实现不一样的提供器,例如:
public class DefaultRunnerProvider : IRunnerProvider
{
#region IRunnerProvider Members
public void Run(Action action)
{
var thread = new Thread(() => action());
thread.Start();
}
#endregion
}
对于后台服务的Host类,经过配置获取注入的接口实例,而Run方法的执行过程则被注入了接口所定义的逻辑,该逻辑由上下文配置所定义:
public class RunnerHost : IDisposable
{
IRunnerProvider provider = null;
public RunnerHost()
{
// Get Provider by configuration
provider = GetProvider(config.Host.Provider.Name);
}
public void Run()
{
if (provider != null)
{
provider.Run(() =>
{
// exceute logic in this provider, if provider is DefualtRunnerProvider,
// then this logic will run in a new thread context.
});
}
}
}
接口注入,为无须从新编译便可修改注入逻辑提供了可能,GetProvider方法彻底能够经过读取配置文件的config.Host.Provider.Name内容,来动态地建立对应的Provider,从而动态地改变BackgroundHost的Run()行为。
public class PicWorker
{
}
public class PicClient
{
private PicWorker worker;
public PicClient(PicWorker worker)
{
// 经过构造器注入
this.worker = worker;
}
}
public class PicClient
{
private PicWorker worker;
// 经过属性注入
public PicWorker Woker
{
get { return this.worker; }
set { this.worker = value; }
}
}
另外,在.NET平台下,除了Martin Flower大师提出的三种注入方式以外,还有一种更优雅的选择,那就是依靠.NET特有的Attribute实现,以ASP .NET MVC中的Action Filter为例:
[HttpPost]
public ActionResult Register(RegisterModel model)
{
// 省略注册过程
return View(model);
}
其中,HttpPostAttribute就是经过Attribute方式为Register Action注入了自动检查Post请求的逻辑,一样的注入方式普遍存在于ASP .NET MVC的不少Filter逻辑中。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class HttpPostAttribute : ActionMethodSelectorAttribute
{
// Fields
private static readonly AcceptVerbsAttribute _innerAttribute = new AcceptVerbsAttribute(HttpVerbs.Post);
// Methods
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
return _innerAttribute.IsValidForRequest(controllerContext, methodInfo);
}
}
关于Attribute的详细内容,请参考8.3节“历史纠葛:特性和属性”,其中的TrimAttribute特性正是应用Attribute注入进行属性Trim过滤处理的典型应用。
转自:http://www.cnblogs.com/jyshis/archive/2011/09/15/2177279.html