예제 #1
0
        public static DynamicMethod CreateObjectToParamListMethod <TParam>(Type objType) where TParam : DbParameter
        {
            var listType     = typeof(List <TParam>);
            var instanceType = typeof(TParam);
            //三个参数,第一个参数是object,第二个参数是参数符号(@,:,?),参数前缀
            DynamicMethod convertMethod = new DynamicMethod("ConvertObjectToParamList" + objType.Name, listType, new Type[] { TypeUtil._ObjectType, TypeUtil._StringType, TypeUtil._StringType }, true);

            ILGenerator  il          = convertMethod.GetILGenerator();
            LocalBuilder listBuilder = il.DeclareLocal(listType);//List<T> 存储对象

            il.SetDefaultObjectValue(listType, listBuilder);

            LocalBuilder objBuilder = il.DeclareLocal(objType);

            il.Emit(OpCodes.Ldarg_0);
            il.SetObjectCastIL(objType);
            il.Emit(OpCodes.Stloc, objBuilder);

            LocalBuilder dbNullBuilder = il.SetDbNullIL();

            List <PropertyInfo> properties = PropertyUtil.GetTypeProperties(objType);

            foreach (var item in properties)
            {
                Label setDbNullLable = il.DefineLabel();                               //设置dbnull
                Label setParamLable  = il.DefineLabel();                               //给param赋值
                Label exitLable      = il.DefineLabel();                               //退出

                LocalBuilder paramNameBuilder = il.DeclareLocal(TypeUtil._StringType); //参数变量名字
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldarg_2);
                il.Emit(OpCodes.Ldstr, item.Name);
                il.Emit(OpCodes.Call, TypeUtil._StringType.GetMethod("Concat", new Type[] { TypeUtil._StringType, TypeUtil._StringType, TypeUtil._StringType }));
                il.Emit(OpCodes.Stloc, paramNameBuilder);

                LocalBuilder instanceBuilder = il.DeclareLocal(instanceType);// T 存储对象
                il.SetDefaultObjectValue(instanceType, instanceBuilder);

                LocalBuilder dbTypeBuilder = il.DeclareLocal(TypeUtil._DbTypeType);
                il.LdcInt((int)TypeUtil.Type2DbType(item.PropertyType));//数据库类型
                il.Emit(OpCodes.Stloc, dbTypeBuilder);

                //设置dbType
                il.Emit(OpCodes.Ldloc, instanceBuilder);
                il.Emit(OpCodes.Ldloc, dbTypeBuilder);
                il.Emit(OpCodes.Callvirt, instanceType.GetMethod("set_DbType", new Type[] { TypeUtil._DbTypeType }));
                //设置ParameterName
                il.Emit(OpCodes.Ldloc, instanceBuilder);
                il.Emit(OpCodes.Ldloc, paramNameBuilder);
                il.Emit(OpCodes.Callvirt, instanceType.GetMethod("set_ParameterName", new Type[] { TypeUtil._StringType }));

                il.Emit(OpCodes.Nop);

                LocalBuilder dbValueBuilder = il.DeclareLocal(TypeUtil._ObjectType);
                var          getMethod      = item.GetGetMethod(true);
                if (getMethod == null)
                {
                    il.Emit(OpCodes.Br_S, setDbNullLable);
                }
                else
                {
                    il.Emit(OpCodes.Ldloc, objBuilder);
                    if (item.DeclaringType.IsValueType && Nullable.GetUnderlyingType(item.DeclaringType) == null)
                    {
                        var t = il.DeclareLocal(item.DeclaringType);
                        il.Emit(OpCodes.Stloc, t);
                        il.Emit(OpCodes.Ldloca_S, t);
                    }
                    if (item.DeclaringType.IsValueType)
                    {
                        il.Emit(OpCodes.Call, getMethod);
                    }
                    else
                    {
                        il.Emit(OpCodes.Callvirt, getMethod);
                    }

                    if (item.PropertyType.IsValueType)
                    {
                        il.Emit(OpCodes.Box, item.PropertyType);
                        if (item.PropertyType.IsEnum)
                        {
                            il.Emit(OpCodes.Ldstr, "d");
                            il.Emit(OpCodes.Call, typeof(Enum).GetMethod("ToString", new Type[] { TypeUtil._StringType }));
                        }
                    }
                    il.Emit(OpCodes.Stloc, dbValueBuilder);
                    il.Emit(OpCodes.Ldloc, dbValueBuilder);
                    il.Emit(OpCodes.Ldnull);
                    il.Emit(OpCodes.Beq_S, setDbNullLable);
                    il.Emit(OpCodes.Br_S, setParamLable);
                }
                il.MarkLabel(setDbNullLable);
                il.Emit(OpCodes.Ldloc, dbNullBuilder);
                il.Emit(OpCodes.Stloc, dbValueBuilder);
                il.Emit(OpCodes.Br_S, setParamLable);

                il.MarkLabel(setParamLable);
                il.Emit(OpCodes.Ldloc, instanceBuilder);
                il.Emit(OpCodes.Ldloc, dbValueBuilder);
                il.Emit(OpCodes.Callvirt, instanceType.GetMethod("set_Value", new Type[] { TypeUtil._ObjectType }));

                il.Emit(OpCodes.Ldloc, listBuilder);
                il.Emit(OpCodes.Ldloc, instanceBuilder);
                il.Emit(OpCodes.Call, listType.GetMethod("Add"));
            }
            il.Emit(OpCodes.Ldloc, listBuilder);
            il.Emit(OpCodes.Ret);
            return(convertMethod);
        }