public static DynamicBuilder <T> CreateBuilder(IDataRecord dataRecord) { DynamicBuilder <T> dynamicBuilder = new DynamicBuilder <T>(); //定义一个名为DynamicCreate的动态方法,返回值typof(T),参数typeof(IDataRecord) DynamicMethod method = new DynamicMethod("DynamicCreate", typeof(T), new Type[] { typeof(IDataRecord) }, typeof(T), true); ILGenerator generator = method.GetILGenerator(); //创建一个MSIL生成器,为动态方法生成代码 LocalBuilder result = generator.DeclareLocal(typeof(T)); //声明指定类型的局部变量 可以T t;这么理解 //The next piece of code instantiates the requested type of object and stores it in the local variable. 可以t=new T();这么理解 generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc, result); for (int i = 0; i < dataRecord.FieldCount; i++) //数据集合,熟悉的for循环 要干什么你懂的 { PropertyInfo propertyInfo = typeof(T).GetProperty(dataRecord.GetName(i)); //根据列名取属性 原则上属性和列是一一对应的关系 Label endIfLabel = generator.DefineLabel(); if (propertyInfo != null && propertyInfo.GetSetMethod() != null)//实体存在该属性 且该属性有SetMethod方法 { /*The code then loops through the fields in the data reader, finding matching properties on the type passed in. * When a match is found, the code checks to see if the value from the data reader is null. */ generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); generator.Emit(OpCodes.Callvirt, isDBNullMethod);//就知道这里要调用IsDBNull方法 如果IsDBNull==true contine generator.Emit(OpCodes.Brtrue, endIfLabel); /*If the value in the data reader is not null, the code sets the value on the object.*/ generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); generator.Emit(OpCodes.Callvirt, getValueMethod); //调用get_Item方法 generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i)); generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); //给该属性设置对应值 generator.MarkLabel(endIfLabel); } } /*The last part of the code returns the value of the local variable*/ generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ret);//方法结束,返回 //完成动态方法的创建,并且创建执行该动态方法的委托,赋值到全局变量handler,handler在Build方法里Invoke dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load)); return(dynamicBuilder); }
/// <summary> /// 执行存储过程读取数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="strProcedure"></param> /// <param name="strErrText"></param> /// <returns></returns> protected List <T> LoadData <T>(string strProcedure, out string strErrText) { List <T> models = new List <T>(); SqlDataReader dr = null; try { SqlCommand command = new SqlCommand(); command.Connection = m_conn; command.CommandTimeout = 7200; command.CommandText = strProcedure; command.CommandType = CommandType.StoredProcedure; m_strInfoMessage = string.Empty; dr = command.ExecuteReader(); DynamicBuilder <T> builder = DynamicBuilder <T> .CreateBuilder(dr); while (dr.Read()) { T model = default(T); model = builder.Build(dr); models.Add(model); } //用于获取存储过程RaiseError命令发出的错误消息。 //如果存储过程中执行了RaiseError命令,则调用NextResult时就会引发异常 dr.NextResult(); dr.Close(); dr.Dispose(); strErrText = string.Empty; return(models); } catch (Exception e) { if (dr != null) { dr.Close(); dr.Dispose(); } strErrText = e.Message; return(null); } }