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 }