动态实现接口 代码
发布日期:2021-09-28 09:31:56 浏览次数:2 分类:技术文章

本文共 16294 字,大约阅读时间需要 54 分钟。

lock (handlers.SyncRoot)

            {
                AppDomain currentAppDomain = AppDomain.CurrentDomain;
                AssemblyName assyName = new AssemblyName();
                assyName.Name = type.FullName;
                AssemblyBuilder assyBuilder = currentAppDomain.DefineDynamicAssembly(assyName, AssemblyBuilderAccess.Run);
                ModuleBuilder modBuilder = assyBuilder.DefineDynamicModule(type.FullName);
                Type[] newTypeInterfaces;
                newTypeInterfaces = new Type[] { typeof(IValueHandler) };
                TypeBuilder typeBuilder =
                    modBuilder.DefineType(
                        "ValueHandler", TypeAttributes.Public);

                typeBuilder.AddInterfaceImplementation(typeof(IValueHandler));

                //PropertyInfo[] infos tmpInfos
                PropertyInfo[] infos = type.GetProperties();

 

                TypeBuilder pidBuilder =

                    modBuilder.DefineType(
                        "<PrivateImplementationDetails>", TypeAttributes.AutoClass | TypeAttributes.AnsiClass);
                FieldBuilder getHashtableBuilder = pidBuilder.DefineField(
                    "$$method0x6000022-1", typeof(Hashtable), FieldAttributes.Static | FieldAttributes.Assembly);
                FieldBuilder setHashtableBuilder = pidBuilder.DefineField(
                    "$$method0x6000023-1", typeof(Hashtable), FieldAttributes.Static | FieldAttributes.Assembly);
                pidBuilder.CreateType();

                MethodBuilder createInstanceMethodBuilder = typeBuilder.DefineMethod(

                    "CreateInstance", MethodAttributes.Public | MethodAttributes.Virtual,
                    typeof(object), null);
                ILGenerator createGenerator = createInstanceMethodBuilder.GetILGenerator();
                createGenerator.DeclareLocal(typeof(object));
                ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);
                if (constructorInfo != null)
                {
                    Label createRet = createGenerator.DefineLabel();
                    createGenerator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
                    createGenerator.Emit(OpCodes.Stloc_0);
                    createGenerator.Emit(OpCodes.Br_S, createRet);
                    createGenerator.MarkLabel(createRet);
                    createGenerator.Emit(OpCodes.Ldloc_0);
                    createGenerator.Emit(OpCodes.Ret);
                }
                else
                {
                    createGenerator.Emit(OpCodes.Ldstr, "The object does not has default constructor");
                    createGenerator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
                    createGenerator.Emit(OpCodes.Throw);
                }

                #region Get

                MethodBuilder getMethodBuilder = typeBuilder.DefineMethod(

                    "GetValue", MethodAttributes.Public | MethodAttributes.Virtual,
                    typeof(object), new Type[] { typeof(object), typeof(string) });
                ILGenerator getGenerator = getMethodBuilder.GetILGenerator();
                getGenerator.DeclareLocal(typeof(object));
                getGenerator.DeclareLocal(typeof(object));

                Label L_0112 = getGenerator.DefineLabel();

                Label L_0256 = getGenerator.DefineLabel();
                Label getRet = getGenerator.DefineLabel();
                Label L_0526 = getGenerator.DefineLabel();
                Label L_054e = getGenerator.DefineLabel();

                ArrayList getLabelArr = new ArrayList();

                for (int i = 0; i < infos.Length; i++)
                {
                    try
                    {
                        MethodInfo minfo = type.GetMethod("get_" + infos[i].Name);
                        if (minfo == null || minfo.GetParameters().Length > 0) continue; //忽略索引器

                        getLabelArr.Add(getGenerator.DefineLabel());

                    }
                    catch { }
                }
                Label[] getLabels = new Label[getLabelArr.Count];
                getLabelArr.CopyTo(getLabels);

                getGenerator.Emit(OpCodes.Volatile);

                getGenerator.Emit(OpCodes.Ldsfld, getHashtableBuilder);
                getGenerator.Emit(OpCodes.Brtrue, L_0112);
                getGenerator.Emit(OpCodes.Ldc_I4, infos.Length);
                getGenerator.Emit(OpCodes.Ldc_R4, .5F);
                getGenerator.Emit(OpCodes.Newobj, typeof(Hashtable).GetConstructor(new Type[] { typeof(Int32), typeof(Single) }));
                for (int i = 0, j = 0; i < infos.Length; i++)
                {
                    try
                    {
                        MethodInfo minfo = type.GetMethod("get_" + infos[i].Name);
                        if (minfo == null || minfo.GetParameters().Length > 0) continue;
                        getGenerator.Emit(OpCodes.Dup);
                        getGenerator.Emit(OpCodes.Ldstr, infos[i].Name);
                        getGenerator.Emit(OpCodes.Ldc_I4_S, j++);
                        getGenerator.Emit(OpCodes.Box, typeof(Int32));
                        getGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("Add", new Type[] { typeof(object), typeof(object) }));
                    }
                    catch { }
                }
                getGenerator.Emit(OpCodes.Volatile);
                getGenerator.Emit(OpCodes.Stsfld, getHashtableBuilder);
                getGenerator.MarkLabel(L_0112);
                getGenerator.Emit(OpCodes.Ldarg_2);
                getGenerator.Emit(OpCodes.Dup);
                getGenerator.Emit(OpCodes.Stloc_1);
                getGenerator.Emit(OpCodes.Brfalse, L_0256);
                getGenerator.Emit(OpCodes.Volatile);
                getGenerator.Emit(OpCodes.Ldsfld, getHashtableBuilder); //  [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000022-1
                getGenerator.Emit(OpCodes.Ldloc_1);
                getGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("get_Item", new Type[] { typeof(object) }));
                getGenerator.Emit(OpCodes.Dup);
                getGenerator.Emit(OpCodes.Stloc_1);
                getGenerator.Emit(OpCodes.Brfalse, L_0256);
                getGenerator.Emit(OpCodes.Ldloc_1);
                getGenerator.Emit(OpCodes.Unbox, typeof(Int32));
                getGenerator.Emit(OpCodes.Ldind_I4);
                getGenerator.Emit(OpCodes.Switch, getLabels);
                getGenerator.Emit(OpCodes.Br, L_0256);

                for (int i = 0, j = 0; i < infos.Length; i++)

                {
                    try
                    {
                        MethodInfo minfo = type.GetMethod("get_" + infos[i].Name);
                        if (minfo == null || minfo.GetParameters().Length > 0) continue;
                        getGenerator.MarkLabel(getLabels[j++]);
                        getGenerator.Emit(OpCodes.Ldarg_1);
                        getGenerator.Emit(OpCodes.Castclass, type);
                        getGenerator.Emit(OpCodes.Callvirt, minfo);
                        if (infos[i].PropertyType.IsValueType)
                            getGenerator.Emit(OpCodes.Box, infos[i].PropertyType);
                        getGenerator.Emit(OpCodes.Stloc_0);
                        getGenerator.Emit(OpCodes.Br, getRet);
                    }
                    catch { }
                }

                getGenerator.MarkLabel(L_0256);

                if (type.BaseType == typeof(Array))
                {
                    getGenerator.Emit(OpCodes.Ldarg_2);
                    getGenerator.Emit(OpCodes.Ldc_I4_0);
                    getGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
                    getGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
                    getGenerator.Emit(OpCodes.Brfalse_S, L_0526);
                    getGenerator.Emit(OpCodes.Ldarg_1);
                    getGenerator.Emit(OpCodes.Castclass, typeof(object[]));
                    getGenerator.Emit(OpCodes.Ldarg_2);
                    getGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
                    getGenerator.Emit(OpCodes.Ldelem_Ref);
                    getGenerator.Emit(OpCodes.Stloc_0);
                    getGenerator.Emit(OpCodes.Br_S, getRet);
                    getGenerator.MarkLabel(L_0526);
                }
                else
                {
                    MethodInfo intIndexer = type.GetMethod("get_Item", new Type[] { typeof(Int32) });
                    //if index is object type, GetMethod will return indexer's MethodInfo whatever type I pass
                    if (intIndexer != null && intIndexer.GetParameters()[0].ParameterType != typeof(object))
                    {
                        getGenerator.Emit(OpCodes.Ldarg_2);
                        getGenerator.Emit(OpCodes.Ldc_I4_0);
                        getGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
                        getGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
                        getGenerator.Emit(OpCodes.Brfalse_S, L_0526);
                        getGenerator.Emit(OpCodes.Ldarg_1);
                        getGenerator.Emit(OpCodes.Castclass, type);
                        getGenerator.Emit(OpCodes.Ldarg_2);
                        getGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
                        getGenerator.Emit(OpCodes.Callvirt, intIndexer);
                        getGenerator.Emit(OpCodes.Stloc_0);
                        getGenerator.Emit(OpCodes.Br_S, getRet);
                        getGenerator.MarkLabel(L_0526);
                    }

                    MethodInfo strIndexer = type.GetMethod("get_Item", new Type[] { typeof(string) });

                    if (strIndexer != null)
                    {
                        getGenerator.Emit(OpCodes.Ldarg_1);
                        getGenerator.Emit(OpCodes.Castclass, type);
                        getGenerator.Emit(OpCodes.Ldarg_2);
                        getGenerator.Emit(OpCodes.Callvirt, strIndexer);
                        getGenerator.Emit(OpCodes.Stloc_0);
                        getGenerator.Emit(OpCodes.Br_S, getRet);
                        getGenerator.MarkLabel(L_054e);
                    }
                }

                getGenerator.Emit(OpCodes.Ldstr, "The property named ");

                getGenerator.Emit(OpCodes.Ldarg_2);
                getGenerator.Emit(OpCodes.Ldstr, " does not exists");
                getGenerator.Emit(OpCodes.Call, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) }));
                getGenerator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
                getGenerator.Emit(OpCodes.Throw);

                getGenerator.MarkLabel(getRet);

                getGenerator.Emit(OpCodes.Ldloc_0);
                getGenerator.Emit(OpCodes.Ret);

                #endregion

                #region Set

                MethodBuilder setMethodBuilder = typeBuilder.DefineMethod(

                    "SetValue", MethodAttributes.Public | MethodAttributes.Virtual, null
                    , new Type[] { typeof(object), typeof(string), typeof(object) });
                ILGenerator setGenerator = setMethodBuilder.GetILGenerator();
                setGenerator.DeclareLocal(typeof(object));

                Label L_0220 = setGenerator.DefineLabel();

                Label L_053b = setGenerator.DefineLabel();
                Label L_0568 = setGenerator.DefineLabel();
                Label L_0593 = setGenerator.DefineLabel();
                Label setRet = setGenerator.DefineLabel();

                ArrayList setLabelList = new ArrayList();

                for (int i = 0; i < infos.Length; i++)
                {
                    try
                    {
                        MethodInfo minfo = type.GetMethod("set_" + infos[i].Name);
                        if (minfo == null || minfo.GetParameters().Length > 1) continue;
                        setLabelList.Add(setGenerator.DefineLabel());
                    }
                    catch { }
                }
                Label[] setLabels = new Label[setLabelList.Count];
                setLabelList.CopyTo(setLabels);

                setGenerator.Emit(OpCodes.Volatile);

                setGenerator.Emit(OpCodes.Ldsfld, setHashtableBuilder);
                setGenerator.Emit(OpCodes.Brtrue, L_0220);
                setGenerator.Emit(OpCodes.Ldc_I4, infos.Length);
                setGenerator.Emit(OpCodes.Ldc_R4, 1F);
                setGenerator.Emit(OpCodes.Newobj, typeof(Hashtable).GetConstructor(new Type[] { typeof(Int32), typeof(Single) }));
                for (int i = 0, j = 0; i < infos.Length; i++)
                {
                    MethodInfo minfo = type.GetMethod("set_" + infos[i].Name);
                    if (minfo == null || minfo.GetParameters().Length > 1) continue;
                    setGenerator.Emit(OpCodes.Dup);
                    setGenerator.Emit(OpCodes.Ldstr, infos[i].Name);
                    setGenerator.Emit(OpCodes.Ldc_I4_S, j++);
                    setGenerator.Emit(OpCodes.Box, typeof(Int32));
                    setGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("Add", new Type[] { typeof(object), typeof(object) }));
                }
                setGenerator.Emit(OpCodes.Volatile);
                setGenerator.Emit(OpCodes.Stsfld, setHashtableBuilder);

                setGenerator.MarkLabel(L_0220);

                setGenerator.Emit(OpCodes.Ldarg_2);
                setGenerator.Emit(OpCodes.Dup);
                setGenerator.Emit(OpCodes.Stloc_0);
                setGenerator.Emit(OpCodes.Brfalse, L_053b);
                setGenerator.Emit(OpCodes.Volatile);
                setGenerator.Emit(OpCodes.Ldsfld, setHashtableBuilder); //  [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000022-1
                setGenerator.Emit(OpCodes.Ldloc_0);
                setGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("get_Item", new Type[] { typeof(object) }));
                setGenerator.Emit(OpCodes.Dup);
                setGenerator.Emit(OpCodes.Stloc_0);
                setGenerator.Emit(OpCodes.Brfalse, L_053b);
                setGenerator.Emit(OpCodes.Ldloc_0);
                setGenerator.Emit(OpCodes.Unbox, typeof(Int32));
                setGenerator.Emit(OpCodes.Ldind_I4);
                setGenerator.Emit(OpCodes.Switch, setLabels);
                setGenerator.Emit(OpCodes.Br, L_053b);

                for (int i = 0, j = 0; i < infos.Length; i++)

                {
                    MethodInfo minfo = type.GetMethod("set_" + infos[i].Name);
                    if (minfo == null || minfo.GetParameters().Length > 1) continue;
                    setGenerator.MarkLabel(setLabels[j++]);
                    setGenerator.Emit(OpCodes.Ldarg_1);
                    setGenerator.Emit(OpCodes.Castclass, type); // NoReflection.TestClass
                    setGenerator.Emit(OpCodes.Ldarg_3);
                    if (infos[i].PropertyType.IsValueType)
                    {
                        setGenerator.Emit(OpCodes.Unbox, infos[i].PropertyType);
                        if (infos[i].PropertyType == typeof(Int64))
                            setGenerator.Emit(OpCodes.Ldind_I8);
                        if (infos[i].PropertyType == typeof(Int32))
                            setGenerator.Emit(OpCodes.Ldind_I4);
                        if (infos[i].PropertyType == typeof(Int16))
                            setGenerator.Emit(OpCodes.Ldind_I2);
                        if (infos[i].PropertyType == typeof(Byte))
                            setGenerator.Emit(OpCodes.Ldind_U1);
                        if (infos[i].PropertyType == typeof(SByte))
                            setGenerator.Emit(OpCodes.Ldind_I1);
                        if (infos[i].PropertyType == typeof(Boolean))
                            setGenerator.Emit(OpCodes.Ldind_I1);
                        if (infos[i].PropertyType == typeof(UInt64))
                            setGenerator.Emit(OpCodes.Ldind_I8);
                        if (infos[i].PropertyType == typeof(UInt32))
                            setGenerator.Emit(OpCodes.Ldind_U4);
                        if (infos[i].PropertyType == typeof(UInt16))
                            setGenerator.Emit(OpCodes.Ldind_U2);
                        if (infos[i].PropertyType == typeof(float))
                            setGenerator.Emit(OpCodes.Conv_R4);
                        if (infos[i].PropertyType == typeof(Decimal))
                            setGenerator.Emit(OpCodes.Ldobj, typeof(Decimal));
                        if (infos[i].PropertyType == typeof(DateTime))
                            setGenerator.Emit(OpCodes.Ldobj, typeof(DateTime));

                    }

                    else
                    {
                        setGenerator.Emit(OpCodes.Castclass, infos[i].PropertyType); // NoReflection.TestClass
                    }
                    setGenerator.Emit(OpCodes.Callvirt, minfo);
                    setGenerator.Emit(OpCodes.Br, setRet);

                }

                setGenerator.MarkLabel(L_053b);

                if (type.BaseType == typeof(Array))
                {
                    setGenerator.Emit(OpCodes.Ldarg_2);
                    setGenerator.Emit(OpCodes.Ldc_I4_0);
                    setGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
                    setGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
                    setGenerator.Emit(OpCodes.Brfalse_S, L_0568);
                    setGenerator.Emit(OpCodes.Ldarg_1);
                    setGenerator.Emit(OpCodes.Castclass, typeof(object[]));
                    setGenerator.Emit(OpCodes.Ldarg_2);
                    setGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
                    setGenerator.Emit(OpCodes.Ldarg_3);
                    setGenerator.Emit(OpCodes.Stelem_Ref);
                    setGenerator.MarkLabel(L_0568);
                    setGenerator.Emit(OpCodes.Br, setRet);
                }
                else
                {
                    PropertyInfo testInfo;
                    testInfo = type.GetProperty("Item", new Type[] { typeof(Int32) });
                    if (testInfo != null)
                    {
                        MethodInfo intSetIndexer = type.GetMethod("set_Item", new Type[] { typeof(Int32), testInfo.PropertyType });
                        if (intSetIndexer != null && intSetIndexer.GetParameters()[0].ParameterType != typeof(object))
                        {
                            setGenerator.Emit(OpCodes.Ldarg_2);
                            setGenerator.Emit(OpCodes.Ldc_I4_0);
                            setGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
                            setGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
                            setGenerator.Emit(OpCodes.Brfalse_S, L_0568);
                            setGenerator.Emit(OpCodes.Ldarg_1);
                            setGenerator.Emit(OpCodes.Castclass, type);
                            setGenerator.Emit(OpCodes.Ldarg_2);
                            setGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
                            setGenerator.Emit(OpCodes.Ldarg_3);
                            setGenerator.Emit(OpCodes.Castclass, typeof(string));
                            setGenerator.Emit(OpCodes.Callvirt, intSetIndexer);
                            setGenerator.Emit(OpCodes.Br, setRet);
                            setGenerator.MarkLabel(L_0568);
                        }
                    }
                    testInfo = type.GetProperty("Item", new Type[] { typeof(String) });
                    if (testInfo != null)
                    {
                        MethodInfo strSetIndexer = type.GetMethod("set_Item", new Type[] { typeof(string), testInfo.PropertyType });
                        if (strSetIndexer != null)
                        {

                            setGenerator.Emit(OpCodes.Ldarg_1);

                            setGenerator.Emit(OpCodes.Castclass, type);
                            setGenerator.Emit(OpCodes.Ldarg_2);
                            setGenerator.Emit(OpCodes.Ldarg_3);
                            if (testInfo.PropertyType.IsValueType)
                            {
                                setGenerator.Emit(OpCodes.Unbox, testInfo.PropertyType);
                                if (testInfo.PropertyType == typeof(Int64))
                                    setGenerator.Emit(OpCodes.Ldind_I8);
                                if (testInfo.PropertyType == typeof(Int32))
                                    setGenerator.Emit(OpCodes.Ldind_I4);
                                if (testInfo.PropertyType == typeof(Int16))
                                    setGenerator.Emit(OpCodes.Ldind_I2);
                                if (testInfo.PropertyType == typeof(Byte))
                                    setGenerator.Emit(OpCodes.Ldind_U1);
                                if (testInfo.PropertyType == typeof(SByte))
                                    setGenerator.Emit(OpCodes.Ldind_I1);
                                if (testInfo.PropertyType == typeof(Boolean))
                                    setGenerator.Emit(OpCodes.Ldind_I1);
                                if (testInfo.PropertyType == typeof(UInt64))
                                    setGenerator.Emit(OpCodes.Ldind_I8);
                                if (testInfo.PropertyType == typeof(UInt32))
                                    setGenerator.Emit(OpCodes.Ldind_U4);
                                if (testInfo.PropertyType == typeof(UInt16))
                                    setGenerator.Emit(OpCodes.Ldind_U2);
                                if (testInfo.PropertyType == typeof(Decimal))
                                    setGenerator.Emit(OpCodes.Ldobj, typeof(Decimal));
                                if (testInfo.PropertyType == typeof(DateTime))
                                    setGenerator.Emit(OpCodes.Ldobj, typeof(DateTime));
                            }
                            else
                            {
                                setGenerator.Emit(OpCodes.Castclass, testInfo.PropertyType);
                            }

                            setGenerator.Emit(OpCodes.Callvirt, strSetIndexer);

                            setGenerator.Emit(OpCodes.Br, setRet);
                            setGenerator.MarkLabel(L_0593);
                        }
                    }
                }
                setGenerator.Emit(OpCodes.Ldstr, "The property named ");
                setGenerator.Emit(OpCodes.Ldarg_2);
                setGenerator.Emit(OpCodes.Ldstr, " does not exists");
                setGenerator.Emit(OpCodes.Call, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) }));
                setGenerator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
                setGenerator.Emit(OpCodes.Throw);
                setGenerator.MarkLabel(setRet);
                setGenerator.Emit(OpCodes.Ret);

                #endregion

                Type t = typeBuilder.CreateType();
                //assyBuilder.Save("ValueHandler." + type.FullName + ".dll");
                IValueHandler result = Activator.CreateInstance(t) as IValueHandler;
                handlers.Add(type, result);
            }

转载地址:https://blog.csdn.net/gooer/article/details/2898023 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Log4net
下一篇:void InvokeHelper( ... );函数的作用

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年03月27日 20时10分50秒