参考文章https://www.cnblogs.com/kklldog/p/3395641.html与https://www.cnblogs.com/MedlarCanFly/p/11430057.html
1 #region 2 3 #region 1.定义IIoCConfig接口 4 public interface IIoCConfig 5 { 6 void AddConfig<TInterface, TType>(); 7 8 Dictionary<Type, Type> ConfigDictionary { get; } 9 } 10 #endregion 11 //试过两者在emit和Activator.CreateInstance两者获得实现。Activator.CreateInstance效率更高 12 #region 2.定义IoCConfig实现 13 14 //使用一个字典来保存Interface跟Class的对应关系。这里是仿造Ninject的配置方式,使用代码来配置。 15 //这种配置方式有个好处就是不会写错,因为有IDE来给你检查拼写错误。不要小看这个好处, 16 //当你有上百个注入对象的时候,使用Unity的XML来配置对应关系的时候很容易就会发生拼写错误。这种错误往往还很难发现。 17 //当然这里要实现一个按照XML配置文件来设置对应关系的类也很容易,这里就不实现了。 18 public class IoCConfig : IIoCConfig 19 { 20 public Dictionary<Type, Type> ConfigDictionary { get; } = new Dictionary<Type, Type>(); 21 22 /// <summary> 23 /// 添加配置 24 /// </summary> 25 /// <typeparam name="TInterface">接口</typeparam> 26 /// <typeparam name="TType">实现接口的类型</typeparam> 27 public void AddConfig<TInterface, TType>() 28 { 29 //判断TType是否实现TInterface 30 if (typeof(TInterface).IsAssignableFrom(typeof(TType))) 31 { 32 ConfigDictionary.Add(typeof(TInterface), typeof(TType)); 33 } 34 else 35 { 36 throw new Exception("类型未实现接口"); 37 } 38 } 39 } 40 #endregion 41 42 #region 3.定义IIoCContainer容器接口 43 /// <summary> 44 /// ioc容器接口 45 /// </summary> 46 public interface IIoCContainer 47 { 48 /// <summary> 49 /// 根据接口返回对应的实例 50 /// </summary> 51 /// <typeparam name="TInterface"></typeparam> 52 /// <returns></returns> 53 TInterface Get<TInterface>(); 54 } 55 #endregion 56 57 #region 4.使用反射实现IoC容器 58 /// <summary> 59 /// 使用反射实现IoC容器 60 /// </summary> 61 public class ReflectionContainer : IIoCContainer 62 { 63 /// <summary> 64 /// 配置实例 65 /// </summary> 66 private IIoCConfig _config; 67 68 /// <summary> 69 /// 构造函数 70 /// </summary> 71 /// <param name="config">ioc配置</param> 72 public ReflectionContainer(IIoCConfig config) 73 { 74 _config = config; 75 } 76 77 /// <summary> 78 /// 根据接口获取实例对象 79 /// </summary> 80 /// <typeparam name="TInterface">接口</typeparam> 81 /// <returns></returns> 82 public TInterface Get<TInterface>() 83 { 84 Type type; 85 var can = _config.ConfigDictionary.TryGetValue(typeof(TInterface), out type); 86 if (can) 87 { 88 //反射实例化对象 89 return (TInterface)Activator.CreateInstance(type); 90 } 91 else 92 { 93 throw new Exception("未找到对应的类型"); 94 } 95 } 96 } 97 #endregion 98 /// <summary> 99 /// 使用Emit实现IoC容器 100 /// </summary> 101 public class EmitContainer : IIoCContainer 102 { 103 /// <summary> 104 /// 配置实例 105 /// </summary> 106 private IIoCConfig _config; 107 108 public EmitContainer(IIoCConfig config) 109 { 110 _config = config; 111 } 112 113 /// <summary> 114 /// 获取实例 115 /// </summary> 116 /// <typeparam name="TInterface">接口</typeparam> 117 /// <returns></returns> 118 public TInterface Get<TInterface>() 119 { 120 Type type; 121 var can = _config.ConfigDictionary.TryGetValue(typeof(TInterface), out type); 122 if (can) 123 { 124 BindingFlags defaultFlags = BindingFlags.Public | BindingFlags.Instance; 125 var constructors = type.GetConstructors(defaultFlags);//获取默认构造函数 126 var t = (TInterface)this.CreateInstanceByEmit(constructors[0]); 127 return t; 128 } 129 else 130 { 131 throw new Exception("未找到对应的类型"); 132 } 133 } 134 135 /// <summary> 136 /// 实例化对象 用EMIT 137 /// </summary> 138 /// <typeparam name="T"></typeparam> 139 /// <param name="constructor">构造函数信息</param> 140 /// <returns></returns> 141 private Object CreateInstanceByEmit(ConstructorInfo constructor) 142 { 143 //动态方法 144 var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString("N"), typeof(Object), new[] { typeof(object[]) }, true); 145 //方法IL 146 ILGenerator il = dynamicMethod.GetILGenerator(); 147 //实例化命令 148 il.Emit(OpCodes.Newobj, constructor); 149 //如果是值类型装箱 150 if (constructor.ReflectedType.IsValueType) 151 il.Emit(OpCodes.Box, constructor.ReflectedType); 152 //返回 153 il.Emit(OpCodes.Ret); 154 //用FUNC去关联方法 155 var func = (Func<Object>)dynamicMethod.CreateDelegate(typeof(Func<Object>)); 156 //执行方法 157 return func.Invoke(); 158 } 159 } 160 //Emit的实现是抄自Ninject的实现方式。这里其实就是在手动书写IL。一个简单的书写IL的办法就是先用C#写好代码,然后用Reflector等反编译工具查看生成的IL,然后改成Emit代码。 161 162 /// <summary> 163 /// 实现IoCContainerManager 164 /// </summary> 165 public class IoCContainerManager 166 { 167 /// <summary> 168 /// 容器 169 /// </summary> 170 private static IIoCContainer _container; 171 172 /// <summary> 173 /// 获取IOC容器 174 /// </summary> 175 /// <param name="config">ioc配置</param> 176 /// <returns></returns> 177 public static IIoCContainer GetIoCContainer(IIoCConfig config) 178 { 179 180 if (_container == null) 181 { 182 //反射方式 183 _container = new ReflectionContainer(config); 184 //EMIT方式 185 // _container=new EmitContainer(config); 186 } 187 return _container; 188 189 } 190 } 191 192 #endregion