前言
在上一篇我大致的介绍了这个系列所涉及到的知识点,在本篇我打算把IOC这一块单独提取出来讲,因为IOC容器在解除框架层与层之间的耦合有着不可磨灭的作用。当然在本系列前面的三篇中我也提供了一种基于反射的解耦方式,但是始终不是很优雅,运用到项目中显得别扭。目前,我所掌握的IOC容器主要有两个:一个是 unity,另一个则是spring.net,经过慎重的思考我还是决定选择unity 2.0做为本系列的IOC容器,原因主要有两个:第一,他是一个轻量级的容器且师出名门(微软),第二,它提供了简单的拦截机制,在它的基础上实现AOP显得非常的简单,下面开始我们今天的议题......
什么是IOC容器
IOC容器是对控制反转与依赖注入的一种实现,关于什么是控制反转,什么是依赖注入,网上一搜一大把,我这里就不在多说了,我们需要关注的就是IOC容器到底能够为我们做些什么事情,其实说白了,IOC容器就是通过相应的配置,用来为我们创建实例,使我们摆脱了new的魔咒,这在层与层之间的解耦中有着重要的意义,至于层次间为什么要解耦请参见我的第一篇, 本文着重介绍unity 2.0,您需要在项目中添加对Microsoft.Practices.Unity.dll与Microsoft.Practices.Unity.Configuration.dll的引用,下面我通过简单doom来讲述它的运用,程序如图
IOC项目引用了IService项目,但并未引用service项目,IService项目中定义的是服务接口,Service项目引用了IService项目并实现了里面的服务接口。我们现在要做的事情就是在IOC中采用IService接口标识服务,在调用时采用unity容器读取配置文件帮助我们把接口实例化,其具体的服务来自Service项目(我们的IOC项目没有引用Service项目所以是无法new的),为了很好的运用Unity容器,我做了一下封装,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.Configuration; using System.Configuration; using System.Reflection; namespace IOC { public class ServiceLocator { /// <summary> /// IOC容器 /// </summary> private readonly IUnityContainer container; private static readonly ServiceLocator instance = new ServiceLocator(); /// <summary> /// 服务定位器单例 /// </summary> public static ServiceLocator Instance { get { return instance; } } private ServiceLocator() { //读取容器配置文件 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); //创建容器 container = new UnityContainer(); //配置容器 section.Configure(container); } #region /// <summary> /// 创建构造函数参数 /// </summary> /// <param name="overridedArguments"></param> /// <returns></returns> private IEnumerable<ParameterOverride> GetParameterOverrides(object overridedArguments) { List<ParameterOverride> overrides = new List<ParameterOverride>(); Type argumentsType = overridedArguments.GetType(); argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .ToList() .ForEach(property => { var propertyValue = property.GetValue(overridedArguments, null); var propertyName = property.Name; overrides.Add(new ParameterOverride(propertyName, propertyValue)); }); return overrides; } #endregion #region 公共方法 /// <summary> /// 创建指定类型的容器 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public T GetService<T>() { return container.Resolve<T>(); } /// <summary> /// 根据指定名称的注册类型 /// 创建指定的类型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="name">注册类型配置节点名称</param> /// <returns></returns> public T GetService<T>(string name) { return container.Resolve<T>(name); } /// <summary> /// 用指定的构造函数参数 /// 创建实体 /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="overridedArguments">属性名对应参数名,属性值对应 /// 参数值得动态参数实体</param> /// <returns></returns> public T GetService<T>(object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve<T>(overrides.ToArray()); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="name"></param> /// <param name="overridedArguments"></param> /// <returns></returns> public T GetService<T>(string name,object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve<T>(name, overrides.ToArray()); } #endregion } }