Unity IoC Base On MVC
Unity框架,是一个经典的IoC模式实现方式,其通过config文件配置section,将接口与实现解藕,config中的section配置的container以全名称对应,使得应用程序无需像Ninject方式那样,依赖接口项和实现项,因其解藕的配置,能让应用程序实现静态更新服务的效果,即不退出应用程序更新服务的功能。
下面是Unity的实现,其核心接口IUnityContainer是Unity模式实现的基础,在Controller生命周期中IUnityContainer起到传递section配置的作用,在Controller实例化时创建依赖的接口服务的实例对象,当Countroller执行结束后,接口服务的实例对象交由IUnityContainer维护
首先需要安装Unity,引用以下两个dll
接下来实现Unity的管理类,新建mvc5网站项目,并如下实现
public class UnityControllerFactory : DefaultControllerFactory { static object syncHelper = new object(); static Dictionary<string, IUnityContainer> containers = new Dictionary<string, IUnityContainer>(); public IUnityContainer UnityContainer { get; private set; } public UnityControllerFactory(string containerName = "") { if (containers.ContainsKey(containerName)) { this.UnityContainer = containers[containerName]; return; } lock (syncHelper) { if (containers.ContainsKey(containerName)) { this.UnityContainer = containers[containerName]; return; } IUnityContainer container = new UnityContainer(); //配置UnityContainer UnityConfigurationSection configSection = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection; if (null == configSection && !string.IsNullOrEmpty(containerName)) { throw new ConfigurationErrorsException("The <unity> configuration section does not exist."); } if (null != configSection) { if (string.IsNullOrEmpty(containerName)) { configSection.Configure(container); } else { configSection.Configure(container, containerName); } } containers.Add(containerName, container); this.UnityContainer = containers[containerName]; } } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { if (null == controllerType) { return null; } return (IController)this.UnityContainer.Resolve(controllerType); } public override void ReleaseController(IController controller) { this.UnityContainer.Teardown(controller); } }
假设有一个服务接口在一个独立的C#类库名为MyInterface
public interface IEmployeeRepository { IEnumerable<Employee> GetEmployees(string id = ""); }
和服务接口的实现项在一个独立的C#类库名为MyService
public class EmployeeRepository: IEmployeeRepository { private static IList<Employee> employees; static EmployeeRepository() { employees = new List<Employee>(); employees.Add(new Employee(Guid.NewGuid().ToString(), "张三", "男", new DateTime(1981, 8, 24), "销售部")); employees.Add(new Employee(Guid.NewGuid().ToString(), "李四", "女", new DateTime(1982, 7, 10), "人事部")); employees.Add(new Employee(Guid.NewGuid().ToString(), "王五", "男", new DateTime(1981, 9, 21), "人事部")); } public IEnumerable<Employee> GetEmployees(string id = "") { return employees.Where(e => e.Id == id || string.IsNullOrEmpty(id) || id == "*"); } }
在上面新建的mvc5网站项目中,引用MyInterface的C#类库,在网站的global文件中Application_Start中添加如下这句,将我们创建的UnityControllerFactory注入给ControllerBuilder初始化
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());
在mvc5网站的web.config中添加section接口服务map信息,将接口与其服务实现类信息配置给Unity
<unity> <containers> <container> <register type="Mvc.IEmployeeRepository, Mvc.MvcApp" mapTo="Mvc.EmployeeRepository, Mvc.MvcApp"/> </container> </containers> </unity>
Unity与于Ninject的好处很明显,接口与实现解藕,无需直接依赖实现项,达到静态更新的效果,在应用程序运行时,只需将实现项的DLL(此处即为MyService.dll)下载替换,即可实现服务更新,要实现自动化静态更新当然需要做些工作,比如MyService应该需要版本检测及下载功能,有兴趣的可以做做
如果想深入了解Unity的对象管理,可以看看老A的这篇文章, 本文参考老A的MVC IoC系列文章
http://www.cnblogs.com/artech/archive/2010/07/13/IoC_Unity_Build.html