前言:在平时的写代码中为了解耦、方便扩展,经常使用一些DI容器(如:Autofac、Unity),那是特别的好用。
关于它的底层实现代码 大概是这样。
一、使用依赖注入的好处
关于使用依赖注入创建对象的好处网上一找就是一大堆(低耦合、可配置等),这里就不复制粘贴了。
二、使用XML+Assembly实现可配置的Container
namespace com.cqgc.TestSys.Core { public class Container { private static Container instance;//实例 private static XDocument xml;//UI层的服务实现配置文件实例 public static Container Instance//全局IOC窗口实例,单例模式 { get { if (instance == null) { instance = new Container(); } if (xml == null) { //读取UI层的服务实现配置文件 xml = XDocument.Load(AppDomain.CurrentDomain.BaseDirectory + "/Configuration/Service.xml"); } return instance; } } /// <summary> /// 向外提供创建对象的方法 /// </summary> /// <typeparam name="T">Service</typeparam> /// <returns></returns> public T Resolve<T>() where T : class { return GetComponentInstance<T>(typeof(T).Name); } /// <summary> /// 通过XMl中的Service名创建对应的业务逻辑实体 /// </summary> /// <typeparam name="T">Component</typeparam> /// <param name="service">Service名字</param> /// <returns>Component</returns> public T GetComponentInstance<T>(string service) where T : class { //没找到配置文件 if (xml == null) { throw new ArgumentNullException("没找到配置文件"+ nameof(xml)); } //在UI层的服务实现配置文件根据接口文件名读取实现接口文件的业务逻辑实体 var element = (from p in xml.Root.Elements("element") where p.Attribute("Id").Value.Equals(service) select new { serviceNamespace = p.Attribute("Service").Value, classNamespace = p.Attribute("Class").Value }).FirstOrDefault(); //没找到配置节点 if (string.IsNullOrEmpty(element.classNamespace)) { throw new Exception("配置文件结点" + service + "出错!"); } string[] configs = element.classNamespace.Split(','); //XML配置中接口和业务逻辑实体不成对 if (configs.Length != 2) { throw new Exception("配置文件结点" + service + "出错!"); } ProxyGenerator generator = new ProxyGenerator();//代码生成器 T t = (T)Assembly.Load(configs[1]).CreateInstance(configs[0]);//根据配置文件实例化一个对象 return t; } //释放资源 public void Dispose() { instance = null; xml = null; } } }
三、XML
<?xml version="1.0" encoding="utf-8" ?> <root> <element Id="IUserService" Service="com.cqgc.TestSys.Service.IUserService, com.cqgc.TestSys.Service" Class="com.cqgc.TestSys.Component.UserComponent, com.cqgc.TestSys.Component"></element> <element Id="ISysUserService" Service="com.cqgc.TestSys.Service.ISysUserService, com.cqgc.TestSys.Service" Class="com.cqgc.TestSys.Component.SysUserComponent, com.cqgc.TestSys.Component"></element> </root>
四、调用
var _user=Container.Instance.Resolve<ISysUserService>();