zoukankan      html  css  js  c++  java
  • C# Emit动态代理生成一个实体对象

     1   /// <summary>
     2     /// 使用Emit动态代理收集实体信息
     3     /// </summary>
     4     /// <typeparam name="T">实体类</typeparam>
     5     public class TDynamicBuilder<T>
     6     {
     7         #region 变量区域
     8         private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new[] { typeof(int) });
     9 
    10         private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new[] { typeof(int) });
    11 
    12         private delegate T Load(IDataRecord dataRecord);
    13 
    14         /// <summary>
    15         /// 代理
    16         /// </summary>
    17         private Load Handler;//最终执行动态方法的一个委托 参数是IDataRecord接口
    18         #endregion
    19 
    20         #region 构造函数
    21         private TDynamicBuilder() { }
    22         #endregion
    23 
    24         #region +Build Emit动态代理生成一个实体对象
    25         /// <summary>
    26         /// Emit动态代理生成一个实体对象
    27         /// </summary>
    28         /// <param name="dataRecord">DataReader接口实现对象</param>
    29         /// <returns></returns>
    30         public T Build(IDataRecord dataRecord)
    31         {
    32             return Handler(dataRecord);//执行CreateBuilder里创建的DynamicCreate动态方法的委托
    33         }
    34         #endregion
    35 
    36         #region + CreateBuilder 创建一个Builder器
    37         /// <summary>
    38         /// 创建一个Builder器
    39         /// </summary>
    40         /// <param name="dataRecord">DataReader接口实现对象</param>
    41         /// <returns></returns>
    42         public static TDynamicBuilder<T> CreateBuilder(IDataRecord dataRecord)
    43         {
    44             var dynamicBuilder = new TDynamicBuilder<T>();
    45             var type = typeof(T);
    46             //定义一个名为DynamicCreate的动态方法,返回值typof(T),参数typeof(IDataRecord)
    47             var method = new DynamicMethod("DynamicCreate", type, new[] { typeof(IDataRecord) }, typeof(T), true);
    48             var generator = method.GetILGenerator();//创建一个MSIL生成器,为动态方法生成代码
    49             var result = generator.DeclareLocal(type);//声明指定类型的局部变量 可以T t;这么理解
    50             //The next piece of code instantiates the requested type of object and stores it in the local variable. 可以t=new T();这么理解
    51             generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
    52             generator.Emit(OpCodes.Stloc, result);
    53             var propertys = type.GetProperties();
    54             //数据集合
    55             for (var i = 0; i < dataRecord.FieldCount; i++)
    56             {
    57                 //查找属性
    58                 var propertyInfo = propertys.FirstOrDefault(a => string.Equals(a.Name.ToLower(), dataRecord.GetName(i).ToLower()));
    59                 if (propertyInfo == null) continue;
    60                 if (!string.Equals(propertyInfo.Name, dataRecord.GetName(i), StringComparison.CurrentCultureIgnoreCase)) continue;
    61                 //根据列名取属性  原则上属性和列是一一对应的关系
    62                 var endIfLabel = generator.DefineLabel();
    63 
    64                 /*The code then loops through the fields in the data reader, finding matching properties on the type passed in. 
    65                  * When a match is found, the code checks to see if the value from the data reader is null.
    66                  */
    67                 generator.Emit(OpCodes.Ldarg_0);
    68                 generator.Emit(OpCodes.Ldc_I4, i);
    69                 //就知道这里要调用IsDBNull方法 如果IsDBNull==true contine
    70                 generator.Emit(OpCodes.Callvirt, isDBNullMethod);
    71                 generator.Emit(OpCodes.Brtrue, endIfLabel);
    72 
    73                 /*If the value in the data reader is not null, the code sets the value on the object.*/
    74                 generator.Emit(OpCodes.Ldloc, result);
    75                 generator.Emit(OpCodes.Ldarg_0);
    76                 generator.Emit(OpCodes.Ldc_I4, i);
    77                 generator.Emit(OpCodes.Callvirt, getValueMethod); //调用get_Item方法
    78                 generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i));
    79                 generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); //给该属性设置对应值
    80 
    81                 generator.MarkLabel(endIfLabel);
    82 
    83             }
    84 
    85             /*The last part of the code returns the value of the local variable*/
    86             generator.Emit(OpCodes.Ldloc, result);
    87             generator.Emit(OpCodes.Ret);//方法结束,返回
    88 
    89             //完成动态方法的创建,并且创建执行该动态方法的委托,赋值到全局变量handler,handler在Build方法里Invoke
    90             dynamicBuilder.Handler = (Load)method.CreateDelegate(typeof(Load));
    91             return dynamicBuilder;
    92         }
    93         #endregion
    94 
    95     }
  • 相关阅读:
    UOS安装gitlab
    docker中连接sqlserver 2008R2(SP3) 失败解决方法
    AtCoder AGC020 E-Encoding Subsets
    CF1553H XOR and Distance
    CF1039E Summer Oenothera Exhibition
    HDOJ 6991 Increasing Subsequence
    HDOJ 6964 I love counting
    Topcoder 15279 SpanningSubgraphs
    全程NOIP计划 题目选做
    分层图总结
  • 原文地址:https://www.cnblogs.com/gaobing/p/5125198.html
Copyright © 2011-2022 走看看