/// <summary> /// 构造转换动态方法(核心代码),根据assembly可处理datarow和datareader两种转换 /// </summary> /// <typeparam name="T">返回的实体类型</typeparam> /// <param name="assembly">待转换数据的元数据信息</param> /// <returns>实体对象</returns> private static DynamicMethod BuildMethod <T>(DynamicAssembleInfo assembly, MapColumn[] mapColumns = null, string methodName = "") { if (methodName == null) { methodName = ""; } DynamicMethod method = new DynamicMethod(methodName + assembly.MethodName + typeof(T).Name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(T), new Type[] { assembly.SourceType }, typeof(EntityContext).Module, true); ILGenerator generator = method.GetILGenerator(); LocalBuilder result = generator.DeclareLocal(typeof(T)); generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc, result); foreach (var column in mapColumns) { PropertyInfo property = column.Property; var endIfLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); //第一组,调用AssembleInfo的CanSetted方法,判断是否可以转换 generator.Emit(OpCodes.Ldstr, column.ColumnName); generator.Emit(OpCodes.Call, assembly.CanSettedMethod); generator.Emit(OpCodes.Brfalse, endIfLabel); //第二组,属性设置 generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldstr, column.ColumnName); generator.Emit(OpCodes.Call, assembly.GetValueMethod);//获取数据库值 if (property.PropertyType.IsValueType || property.PropertyType == typeof(string)) { var cur = Nullable.GetUnderlyingType(property.PropertyType); generator.Emit(OpCodes.Call, ConvertMethods[cur == null?property.PropertyType:cur]);//调用强转方法赋值 if (cur != null) { generator.Emit(OpCodes.Newobj, property.PropertyType.GetConstructor(new Type[] { cur })); } } //效果类似 Name=Convert.ToString(row["PName"]); else { generator.Emit(OpCodes.Castclass, property.PropertyType); } generator.Emit(OpCodes.Call, property.GetSetMethod());//直接给属性赋值 //效果类似 Name=row["PName"]; generator.MarkLabel(endIfLabel); } generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ret); return(method); }
/// <summary> /// 构造转换动态方法(核心代码),根据assembly可处理datarow和datareader两种转换 /// </summary> /// <typeparam name="T">返回的实体类型</typeparam> /// <param name="assembly">待转换数据的元数据信息</param> /// <returns>实体对象</returns> private static DynamicMethod BuildMethod <T>(DynamicAssembleInfo assembly, MapColumn[] mapColumns = null, string methodName = "") { if (methodName == null) { methodName = ""; } DynamicMethod method = new DynamicMethod(methodName + assembly.MethodName + typeof(T).Name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(T), new Type[] { assembly.SourceType }, typeof(EntityContext).Module, true); ILGenerator generator = method.GetILGenerator(); LocalBuilder result = generator.DeclareLocal(typeof(T)); generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc, result); foreach (var column in mapColumns) { PropertyInfo property = column.Property; var endIfLabel = generator.DefineLabel(); var tmpIfLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); //第一组,调用AssembleInfo的CanSetted方法,判断是否可以转换 generator.Emit(OpCodes.Ldstr, column.ColumnName); generator.Emit(OpCodes.Call, assembly.CanSettedMethod); generator.Emit(OpCodes.Brfalse, endIfLabel); //第二组,属性设置 generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldstr, column.ColumnName); generator.Emit(OpCodes.Call, assembly.GetValueMethod);//获取数据库值 if (property.PropertyType.IsValueType || property.PropertyType == typeof(string)) { if (property.PropertyType.IsEnum) { if (column.ColType == "Int32") { generator.Emit(OpCodes.Unbox_Any, property.PropertyType); } else if (column.ColType == "String") { generator.Emit(OpCodes.Ldtoken, property.PropertyType); generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) })); generator.Emit(OpCodes.Call, assembly.EnumConvert); generator.Emit(OpCodes.Unbox_Any, property.PropertyType); } } else { LocalBuilder tmp = null; var cur = Nullable.GetUnderlyingType(property.PropertyType); var tmpType = cur; if (cur == null) { cur = property.PropertyType; } if (column.ColType == "String" && cur == typeof(decimal)) { tmp = generator.DeclareLocal(typeof(object)); var tmpBool = generator.DeclareLocal(typeof(bool)); generator.Emit(OpCodes.Call, ConvertMethods[typeof(string)]); //调用强转方法转; generator.Emit(OpCodes.Stloc, tmp); // generator.Emit(OpCodes.Ldloc, tmp); // generator.Emit(OpCodes.Call, assembly.CanScientific); //调用判断; generator.Emit(OpCodes.Stloc, tmpBool); // generator.Emit(OpCodes.Ldloc, tmpBool); // generator.Emit(OpCodes.Brfalse_S, tmpIfLabel); // generator.Emit(OpCodes.Ldloc, tmp); // generator.Emit(OpCodes.Call, ConvertMethods[typeof(double)]); //调用强转方法转; generator.Emit(OpCodes.Box, typeof(Double)); generator.Emit(OpCodes.Stloc, tmp); } generator.MarkLabel(tmpIfLabel); // if (tmp != null) { generator.Emit(OpCodes.Ldloc, tmp); } generator.Emit(OpCodes.Call, ConvertMethods[cur]);//调用强转方法赋值 if (tmpType != null) { generator.Emit(OpCodes.Newobj, property.PropertyType.GetConstructor(new Type[] { tmpType })); } } } //效果类似 Name=Convert.ToString(row["PName"]); else { generator.Emit(OpCodes.Castclass, property.PropertyType); } generator.Emit(OpCodes.Call, property.GetSetMethod());//直接给属性赋值 //效果类似 Name=row["PName"]; generator.MarkLabel(endIfLabel); } generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ret); return(method); }
/// <summary> /// 构造转换动态方法(核心代码),根据assembly可处理datarow和datareader两种转换 /// </summary> /// <typeparam name="T">返回的实体类型</typeparam> /// <param name="assembly">待转换数据的元数据信息</param> /// <returns>实体对象</returns> private static MethodInfo BuildMethod <T>(DynamicAssembleInfo assembly, MapColumn[] mapColumns = null, string methodName = "") { var asmName = new AssemblyName("MyClass"); //首先就需要定义一个程序集 var defAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); //首先就需要定义一个程序集 //var defAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); //if (methodName==null) //{ // methodName = ""; //} var defModuleBuilder = defAssembly.DefineDynamicModule("MyModule", "MyAssembly.dll"); var defClassBuilder = defModuleBuilder.DefineType("MyClass", TypeAttributes.Public); //定义一个方法 var method = defClassBuilder.DefineMethod("MyMethod", MethodAttributes.Public, typeof(T),//返回类型 new Type[] { assembly.SourceType }//参数的类型 ); //DynamicMethod method = new DynamicMethod(methodName+assembly.MethodName + typeof(T).Name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(T), // new Type[] { assembly.SourceType }, typeof(EntityContext).Module, true); ILGenerator generator = method.GetILGenerator(); LocalBuilder result = generator.DeclareLocal(typeof(T)); generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc, result); foreach (var column in mapColumns) { PropertyInfo property = column.Property; var endIfLabel = generator.DefineLabel(); var tmpIfLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_1); //第一组,调用AssembleInfo的CanSetted方法,判断是否可以转换 generator.Emit(OpCodes.Ldstr, column.ColumnName); generator.Emit(OpCodes.Call, assembly.CanSettedMethod); generator.Emit(OpCodes.Brfalse, endIfLabel); //第二组,属性设置 generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldstr, column.ColumnName); generator.Emit(OpCodes.Call, assembly.GetValueMethod);//获取数据库值 if (property.PropertyType.IsValueType || property.PropertyType == typeof(string)) { if (property.PropertyType.IsEnum) { if (column.ColType == "Int32") { generator.Emit(OpCodes.Unbox_Any, property.PropertyType); } else if (column.ColType == "String") { generator.Emit(OpCodes.Ldtoken, property.PropertyType); generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) })); generator.Emit(OpCodes.Call, assembly.EnumConvert); generator.Emit(OpCodes.Unbox_Any, property.PropertyType); } } else { LocalBuilder tmp = null; var cur = Nullable.GetUnderlyingType(property.PropertyType); var tmpType = cur; if (cur == null) { //不是可空 cur = property.PropertyType; } if (cur == typeof(decimal) && column.ColType == "String") { tmp = generator.DeclareLocal(typeof(object)); var tmpBool = generator.DeclareLocal(typeof(bool)); generator.Emit(OpCodes.Call, ConvertMethods[typeof(string)]); //调用强转方法转; generator.Emit(OpCodes.Stloc, tmp); // generator.Emit(OpCodes.Ldloc, tmp); // generator.Emit(OpCodes.Call, assembly.CanScientific); //调用强转方法转; generator.Emit(OpCodes.Stloc, tmpBool); // generator.Emit(OpCodes.Ldloc, tmpBool); // generator.Emit(OpCodes.Brfalse_S, tmpIfLabel); // generator.Emit(OpCodes.Ldloc, tmp); // generator.Emit(OpCodes.Call, ConvertMethods[typeof(double)]); //调用强转方法转; generator.Emit(OpCodes.Box, typeof(Double)); generator.Emit(OpCodes.Stloc, tmp); } generator.MarkLabel(tmpIfLabel); // if (tmp != null) { generator.Emit(OpCodes.Ldloc, tmp); } generator.Emit(OpCodes.Call, ConvertMethods[cur]);//调用强转方法赋值 if (tmpType != null) { //说明是可空 generator.Emit(OpCodes.Newobj, property.PropertyType.GetConstructor(new Type[] { tmpType })); } } } //效果类似 Name=Convert.ToString(row["PName"]); else { generator.Emit(OpCodes.Castclass, property.PropertyType); } generator.Emit(OpCodes.Call, property.GetSetMethod()); //直接给属性赋值 //效果类似 Name=row["PName"]; generator.Emit(OpCodes.Nop); generator.MarkLabel(endIfLabel); } generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ret); // 创建类型 var defTYpe = defClassBuilder.CreateType(); objtar = defTYpe; var mth = defTYpe.GetMethod("MyMethod"); defAssembly.SetEntryPoint(mth); //保存程序集 defAssembly.Save("MyAssemblydll"); return(mth); }