zoukankan      html  css  js  c++  java
  • IoC原理-使用反射/Emit来实现一个最简单的IoC容器

    参考文章https://www.cnblogs.com/kklldog/p/3395641.htmlhttps://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
    View Code
  • 相关阅读:
    javascript入门篇(五)
    javascript入门篇(四)
    javascript入门篇(三)
    原生js查询、添加、删除类
    关于禁止复制网页内容应该做的兼容
    json快速入门
    jquery快速入门(五)
    jquery快速入门(四)
    jquery快速入门(三)
    Triangle 1.6 (A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator)
  • 原文地址:https://www.cnblogs.com/hudean/p/11771510.html
Copyright © 2011-2022 走看看