private void Prepare(IDataRecord dataRecord) { // 定义一个动态方法,返回类型 typeof(T),输入类型 typeof(IDataRecord) Type type = typeof(T); string name = string.Format("Create{0}", type.Name); DynamicMethod dynamicMethod; if (DynamicMethodContainer.IsExist(name)) { dynamicMethod = DynamicMethodContainer.Get(name); } else { Dictionary <string, int> dictionary = Match(dataRecord); dynamicMethod = new DynamicMethod( name, type, new Type[] { typeof(IDataRecord) }, type, true); // 创建一个MSIL生成器,为动态方法生成代码 ILGenerator generator = dynamicMethod.GetILGenerator(); // 声明指定类型的局部变量,可以理解为 T t; LocalBuilder localBuilder = generator.DeclareLocal(type); // 可以理解为 T t = new T(); The next piece of code instantiates the requested type of object and stores it in the local variable. ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes); generator.Emit(OpCodes.Newobj, constructorInfo); generator.Emit(OpCodes.Stloc, localBuilder); foreach (string propertyName in dictionary.Keys) { PropertyInfo propertyInfo = type.GetProperty(propertyName); int index = dictionary[propertyName]; // 定义标签 Label endIfLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, index); // 调用 Callvirt : dataRecord.IsDBNull() 方法 generator.Emit(OpCodes.Callvirt, isDBNullMethod); // 如果是 DataRecord.IsDBNull() == true 则 contine generator.Emit(OpCodes.Brtrue, endIfLabel); generator.Emit(OpCodes.Ldloc, localBuilder); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, index); // 调用 Callvirt : dataRecord.get_Item(i) 方法 generator.Emit(OpCodes.Callvirt, getItemMethod); generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(index)); // 调用 Callvirt : propertyInfo.GetSetMethod 方法 generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); // 在当前 MSIL 流位置进行标记 generator.MarkLabel(endIfLabel); } // The last part of the code returns the value of the local variable generator.Emit(OpCodes.Ldloc, localBuilder); // 方法结束 generator.Emit(OpCodes.Ret); DynamicMethodContainer.Add(name, dynamicMethod); } // 完成动态方法的创建并创建执行该动态方法的委托 // DataRecord2Entity 在 Build 方法里实现 this.dataRecord2Entity = (DataRecord2Entity)dynamicMethod.CreateDelegate(typeof(DataRecord2Entity)); }
/// 定义一个动态方法,返回类型 typeof(T),输入类型 typeof(IDataRecord) /// <remarks> /// if (DynamicMethodContainer.IsExist(name)) /// { /// DynamicMethod dynamicMethod = DynamicMethodContainer.Get(name); /// } /// else /// { /// DynamicMethodContainer.Add(name, dynamicMethod); /// } /// </remarks> protected void PrepareDelegate(IDataRecord dataRecord) { string name = string.Format("Create{0}", this.type.Name); Type[] parameterTypes = new Type[] { typeof(IDataRecord) }; DynamicMethod dynamicMethod = new DynamicMethod(name, this.type, parameterTypes, this.type, true); // 创建一个MSIL生成器,为动态方法生成代码 ILGenerator generator = dynamicMethod.GetILGenerator(); // 声明指定类型的局部变量,可以理解为 T t; LocalBuilder localBuilder = generator.DeclareLocal(this.type); // PUSH : T t = new T(); // Instantiates the requested type of object and stores it in the local variable. ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes); generator.Emit(OpCodes.Newobj, constructorInfo); generator.Emit(OpCodes.Stloc, localBuilder); Dictionary <int, string> dictionary = this.Match(dataRecord); foreach (int i in dictionary.Keys) { string propertyName = dictionary[i]; PropertyInfo propertyInfo = this.type.GetProperty(propertyName); // 定义标签 Label endIfLabel = generator.DefineLabel(); // 调用 Callvirt : IDataRecord.IsDBNull() 方法 generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); generator.Emit(OpCodes.Callvirt, IsDBNullMethod); // 如果是 DataRecord.IsDBNull() == true 则 contine generator.Emit(OpCodes.Brtrue, endIfLabel); // POP : T t generator.Emit(OpCodes.Ldloc, localBuilder); // 调用 Callvirt : IDataRecord.get_Item(i) 方法 generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); generator.Emit(OpCodes.Callvirt, getItemMethod); //Ad By RQ 2011-01-18 12:46 ORACLE DATE 用 dataRecord.GetFieldType(i) 得出的类型转换出错 //generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i)); generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); // 调用 Callvirt : propertyInfo.GetSetMethod 方法 generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); // 在当前 MSIL 流位置进行标记 generator.MarkLabel(endIfLabel); } // returns the value of the local variable generator.Emit(OpCodes.Ldloc, localBuilder); // 方法结束 generator.Emit(OpCodes.Ret); // 完成动态方法的创建并创建执行该动态方法的委托 this.dataRecord2Entity = (DataRecord2Entity)dynamicMethod.CreateDelegate(typeof(DataRecord2Entity)); }