/// <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);
        }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
        /// <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);
        }