在 ILGenerator 中,对内部 setter 的调用失败

发布于 2024-12-08 08:50:53 字数 5754 浏览 1 评论 0原文

为了能够在运行时操作属性,我尝试构建一个通用包装器,它将所有公共/非公共、静态/实例属性转换为 PropertyGrid 控件中可见的公共实例属性。

下面的代码适用于公共 setter 和 getter(静态和实例),但对于具有内部作用域的 setter 则失败。

非常感谢任何帮助。

public static class PropertyWrapper<T> where T : class
{
    public const BindingFlags DefaultBindingFlags = BindingFlags.Public
                                                  | BindingFlags.NonPublic
                                                  | BindingFlags.Static
                                                  | BindingFlags.Instance;

    public static object Instance(T obj)
    {
        return Instance(obj, true, DefaultBindingFlags);
    }

    public static object Instance(T obj, bool readOnly)
    {
        return Instance(obj, readOnly, DefaultBindingFlags);
    }

    public static object Instance(T wrappedObject, bool readOnly, BindingFlags bindingFlags)
    {
        string commonName = "propertyWrapperModule.dll";
        FieldAttributes fieldAttributes = FieldAttributes.Public;

        string wrapperTypeName          = wrappedObject.GetType().Name + "_WRAPPER";
        AssemblyName assemblyName       = new AssemblyName { Name = "commonName" };
        AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder moduleBuilder     = assemblyBuilder.DefineDynamicModule(commonName);
        TypeBuilder typeBuilder         = moduleBuilder.DefineType(wrapperTypeName, TypeAttributes.Public | TypeAttributes.Class);

        var objProperties = wrappedObject.GetType().GetProperties(bindingFlags);
        foreach (var objProperty in objProperties)
        {
            // Field
            FieldBuilder fieldBuilder = typeBuilder.DefineField(objProperty.Name, objProperty.PropertyType, fieldAttributes);

            // Property
            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(objProperty.Name,
                                                PropertyAttributes.None,
                                                objProperty.PropertyType,
                                                new Type[] { objProperty.PropertyType });

            // Define Getter
            if (objProperty.CanRead)
            {
                MethodInfo objGetterMethodInfo = objProperty.GetGetMethod(true);

                if (objGetterMethodInfo != null)
                {
                    MethodBuilder getterMethodBuilder = DefineGetter(objGetterMethodInfo, typeBuilder, fieldBuilder);
                    propertyBuilder.SetGetMethod(getterMethodBuilder);
                }
            }

            // Define Setter
            if (objProperty.CanWrite)
            {
                MethodInfo objSetterMethodInfo = objProperty.GetSetMethod(true);

                if (objSetterMethodInfo != null)
                {
                    MethodBuilder methodBuilderSetter = DefineSetter(objSetterMethodInfo, typeBuilder, fieldBuilder);       // , objectType);
                    propertyBuilder.SetSetMethod(methodBuilderSetter);
                }
            }
        }

        Type wrapperType = typeBuilder.CreateType();

        var wrapperObject = Activator.CreateInstance(wrapperType);

        // Test
        var wrapperProperties = wrapperType.GetProperties();

        // Save assembly
        assemblyBuilder.Save(commonName);

        return wrapperObject;

    }   // public object CreateNewObject(T obj) 


    private static MethodBuilder DefineGetter(MethodInfo getterMethodInfo, TypeBuilder typeBuilder, FieldBuilder fieldBuilder)  //  Type objectType)
    {
        MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;  // | MethodAttributes.Virtual;

        MethodBuilder getterMethodBuilder = typeBuilder.DefineMethod
        (
            getterMethodInfo.Name,
            attributes,
            getterMethodInfo.ReturnType,
            Type.EmptyTypes
        );

        // Generate IL
        ILGenerator ilGenerator = getterMethodBuilder.GetILGenerator();
        ilGenerator.DeclareLocal(fieldBuilder.FieldType);
        ilGenerator.Emit(OpCodes.Nop);
        if (!getterMethodInfo.IsStatic)
        {
            ilGenerator.Emit(OpCodes.Ldarg_0);
        }
        ilGenerator.EmitCall(OpCodes.Callvirt, getterMethodInfo, null);
        ilGenerator.Emit(OpCodes.Stloc_0);
        // http://stackoverflow.com/questions/6766839/using-br-s-opcode-to-point-to-next-instruction-using-reflection-emit-label
        Label targetInstruction = ilGenerator.DefineLabel();
        ilGenerator.Emit(OpCodes.Br_S, targetInstruction);
        ilGenerator.MarkLabel(targetInstruction);
        ilGenerator.Emit(OpCodes.Ldloc_0);
        ilGenerator.Emit(OpCodes.Ret);

        return getterMethodBuilder;
    }

    private static MethodBuilder DefineSetter(MethodInfo setterMethodInfo, TypeBuilder typeBuilder, FieldBuilder fieldBuilder)  
    {
        MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;  

        MethodBuilder setterMethodBuilder = typeBuilder.DefineMethod
        (
            setterMethodInfo.Name,
            attributes,
            null,
            new Type[] { fieldBuilder.FieldType }
        );

        // Generate IL
        ILGenerator ilGenerator = setterMethodBuilder.GetILGenerator();
        ilGenerator.Emit(OpCodes.Nop);
        if (!setterMethodInfo.IsStatic)
        {
            ilGenerator.Emit(OpCodes.Ldarg_0);
        }
        ilGenerator.Emit(OpCodes.Ldarg_1);
        ilGenerator.EmitCall(OpCodes.Callvirt, setterMethodInfo, null);
        ilGenerator.Emit(OpCodes.Ret);
        return setterMethodBuilder;
    }
}

To be able to manipulate properties at runtime, I am trying to build a generic wrapper that would convert all public/non-public , static/instance properties into public instance properties visible in PropertyGrid control.

The code below works fine for public setters and getters (both static and instance), yet fails for, say, setters having internal scope.

Any help is greatly appreciated.

public static class PropertyWrapper<T> where T : class
{
    public const BindingFlags DefaultBindingFlags = BindingFlags.Public
                                                  | BindingFlags.NonPublic
                                                  | BindingFlags.Static
                                                  | BindingFlags.Instance;

    public static object Instance(T obj)
    {
        return Instance(obj, true, DefaultBindingFlags);
    }

    public static object Instance(T obj, bool readOnly)
    {
        return Instance(obj, readOnly, DefaultBindingFlags);
    }

    public static object Instance(T wrappedObject, bool readOnly, BindingFlags bindingFlags)
    {
        string commonName = "propertyWrapperModule.dll";
        FieldAttributes fieldAttributes = FieldAttributes.Public;

        string wrapperTypeName          = wrappedObject.GetType().Name + "_WRAPPER";
        AssemblyName assemblyName       = new AssemblyName { Name = "commonName" };
        AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder moduleBuilder     = assemblyBuilder.DefineDynamicModule(commonName);
        TypeBuilder typeBuilder         = moduleBuilder.DefineType(wrapperTypeName, TypeAttributes.Public | TypeAttributes.Class);

        var objProperties = wrappedObject.GetType().GetProperties(bindingFlags);
        foreach (var objProperty in objProperties)
        {
            // Field
            FieldBuilder fieldBuilder = typeBuilder.DefineField(objProperty.Name, objProperty.PropertyType, fieldAttributes);

            // Property
            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(objProperty.Name,
                                                PropertyAttributes.None,
                                                objProperty.PropertyType,
                                                new Type[] { objProperty.PropertyType });

            // Define Getter
            if (objProperty.CanRead)
            {
                MethodInfo objGetterMethodInfo = objProperty.GetGetMethod(true);

                if (objGetterMethodInfo != null)
                {
                    MethodBuilder getterMethodBuilder = DefineGetter(objGetterMethodInfo, typeBuilder, fieldBuilder);
                    propertyBuilder.SetGetMethod(getterMethodBuilder);
                }
            }

            // Define Setter
            if (objProperty.CanWrite)
            {
                MethodInfo objSetterMethodInfo = objProperty.GetSetMethod(true);

                if (objSetterMethodInfo != null)
                {
                    MethodBuilder methodBuilderSetter = DefineSetter(objSetterMethodInfo, typeBuilder, fieldBuilder);       // , objectType);
                    propertyBuilder.SetSetMethod(methodBuilderSetter);
                }
            }
        }

        Type wrapperType = typeBuilder.CreateType();

        var wrapperObject = Activator.CreateInstance(wrapperType);

        // Test
        var wrapperProperties = wrapperType.GetProperties();

        // Save assembly
        assemblyBuilder.Save(commonName);

        return wrapperObject;

    }   // public object CreateNewObject(T obj) 


    private static MethodBuilder DefineGetter(MethodInfo getterMethodInfo, TypeBuilder typeBuilder, FieldBuilder fieldBuilder)  //  Type objectType)
    {
        MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;  // | MethodAttributes.Virtual;

        MethodBuilder getterMethodBuilder = typeBuilder.DefineMethod
        (
            getterMethodInfo.Name,
            attributes,
            getterMethodInfo.ReturnType,
            Type.EmptyTypes
        );

        // Generate IL
        ILGenerator ilGenerator = getterMethodBuilder.GetILGenerator();
        ilGenerator.DeclareLocal(fieldBuilder.FieldType);
        ilGenerator.Emit(OpCodes.Nop);
        if (!getterMethodInfo.IsStatic)
        {
            ilGenerator.Emit(OpCodes.Ldarg_0);
        }
        ilGenerator.EmitCall(OpCodes.Callvirt, getterMethodInfo, null);
        ilGenerator.Emit(OpCodes.Stloc_0);
        // http://stackoverflow.com/questions/6766839/using-br-s-opcode-to-point-to-next-instruction-using-reflection-emit-label
        Label targetInstruction = ilGenerator.DefineLabel();
        ilGenerator.Emit(OpCodes.Br_S, targetInstruction);
        ilGenerator.MarkLabel(targetInstruction);
        ilGenerator.Emit(OpCodes.Ldloc_0);
        ilGenerator.Emit(OpCodes.Ret);

        return getterMethodBuilder;
    }

    private static MethodBuilder DefineSetter(MethodInfo setterMethodInfo, TypeBuilder typeBuilder, FieldBuilder fieldBuilder)  
    {
        MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;  

        MethodBuilder setterMethodBuilder = typeBuilder.DefineMethod
        (
            setterMethodInfo.Name,
            attributes,
            null,
            new Type[] { fieldBuilder.FieldType }
        );

        // Generate IL
        ILGenerator ilGenerator = setterMethodBuilder.GetILGenerator();
        ilGenerator.Emit(OpCodes.Nop);
        if (!setterMethodInfo.IsStatic)
        {
            ilGenerator.Emit(OpCodes.Ldarg_0);
        }
        ilGenerator.Emit(OpCodes.Ldarg_1);
        ilGenerator.EmitCall(OpCodes.Callvirt, setterMethodInfo, null);
        ilGenerator.Emit(OpCodes.Ret);
        return setterMethodBuilder;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

舂唻埖巳落 2024-12-15 08:50:53

这会做到这一点

public static Type BuildWrapper(object targetObject)
{
    Type targetWrapType = targetObject.GetType();

    string nameOfDLL = "magicWrapper.dll";
    string nameOfAssembly = "magic_Assembly";
    string nameOfModule = "magic_Module";
    string nameOfType = "magic_Type";


    System.Reflection.AssemblyName assemblyName = new System.Reflection.AssemblyName {Name = nameOfAssembly};
    System.Reflection.Emit.AssemblyBuilder assemblyBuilder =
        System.Threading.Thread.GetDomain().DefineDynamicAssembly(assemblyName,
                                                                  System.Reflection.Emit.AssemblyBuilderAccess.
                                                                      RunAndSave);
    System.Reflection.Emit.ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(nameOfModule, nameOfDLL);
    System.Reflection.Emit.TypeBuilder typeBuilder = moduleBuilder.DefineType(nameOfType,
                                                                              System.Reflection.TypeAttributes.
                                                                                  Public |
                                                                              System.Reflection.TypeAttributes.Class);


    System.Reflection.Emit.FieldBuilder targetWrapedObjectField =
        typeBuilder.DefineField("_" + targetWrapType.FullName.Replace(".", ""), targetWrapType,
                                System.Reflection.FieldAttributes.Private);
    System.Reflection.MethodAttributes constructorAttributes = System.Reflection.MethodAttributes.Public;

    Type objType = Type.GetType("System.Object");
    System.Reflection.ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
    System.Reflection.Emit.ConstructorBuilder constructorBuilder =
        typeBuilder.DefineConstructor(constructorAttributes, System.Reflection.CallingConventions.Standard,
                                      new Type[] {targetWrapType});

    System.Reflection.Emit.ILGenerator ilConstructor = constructorBuilder.GetILGenerator();
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Call, objCtor);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Nop);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Stfld, targetWrapedObjectField);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Nop);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ret);


    System.Reflection.MethodAttributes propertyAttributes = System.Reflection.MethodAttributes.Public |
                                                            System.Reflection.MethodAttributes.HideBySig |
                                                            System.Reflection.MethodAttributes.SpecialName;

    foreach (var prop in targetObject.GetType().GetFields())
    {
        string Name = prop.Name;
        Type DataType = prop.FieldType;

        System.Reflection.Emit.PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(Name,
                                                                                            System.Reflection.
                                                                                                PropertyAttributes.
                                                                                                SpecialName,
                                                                                            DataType, null);
        System.Reflection.Emit.MethodBuilder methodBuilderGetter = typeBuilder.DefineMethod("get_" + Name,
                                                                                            propertyAttributes,
                                                                                            DataType, new Type[] {});
        System.Reflection.Emit.MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod("set_" + Name,
                                                                                            propertyAttributes,
                                                                                            typeof (void),
                                                                                            new Type[] {DataType});

        System.Reflection.Emit.ILGenerator ilGeneratorGetter = methodBuilderGetter.GetILGenerator();
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, prop);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ret);


        System.Reflection.Emit.ILGenerator ilGeneratorSetter = methodBuilderSetter.GetILGenerator();
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Stfld, prop);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ret);

        propertyBuilder.SetGetMethod(methodBuilderGetter);
        propertyBuilder.SetSetMethod(methodBuilderSetter);
    }


    System.Collections.Generic.List<System.Reflection.PropertyInfo> PropertieList = new List<PropertyInfo>();
    PropertieList.AddRange(targetObject.GetType().GetProperties(BindingFlags.Public));
    PropertieList.AddRange(targetObject.GetType().GetProperties(BindingFlags.NonPublic));

    foreach (var prop in PropertieList)
    {
        string Name = prop.Name;
        Type DataType = prop.PropertyType;

        System.Reflection.Emit.PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(Name,
                                                                                            System.Reflection.
                                                                                                PropertyAttributes.
                                                                                                SpecialName,
                                                                                            DataType, null);
        System.Reflection.Emit.MethodBuilder methodBuilderGetter = typeBuilder.DefineMethod("get_" + Name,
                                                                                            propertyAttributes,
                                                                                            DataType, new Type[] {});
        System.Reflection.Emit.MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod("set_" + Name,
                                                                                            propertyAttributes,
                                                                                            typeof (void),
                                                                                            new Type[] {DataType});

        System.Reflection.Emit.ILGenerator ilGeneratorGetter = methodBuilderGetter.GetILGenerator();
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Callvirt, prop.GetGetMethod());
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Stloc_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldloc_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ret);


        System.Reflection.Emit.ILGenerator ilGeneratorSetter = methodBuilderSetter.GetILGenerator();
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Callvirt, prop.GetSetMethod());
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ret);
        propertyBuilder.SetGetMethod(methodBuilderGetter);
        propertyBuilder.SetSetMethod(methodBuilderSetter);
    }

    // Yes! you must do this, it should not be needed but it is!
    Type dynamicType = typeBuilder.CreateType();

    // Save to file
    assemblyBuilder.Save(nameOfDLL);
    return dynamicType;
}

This will do that

public static Type BuildWrapper(object targetObject)
{
    Type targetWrapType = targetObject.GetType();

    string nameOfDLL = "magicWrapper.dll";
    string nameOfAssembly = "magic_Assembly";
    string nameOfModule = "magic_Module";
    string nameOfType = "magic_Type";


    System.Reflection.AssemblyName assemblyName = new System.Reflection.AssemblyName {Name = nameOfAssembly};
    System.Reflection.Emit.AssemblyBuilder assemblyBuilder =
        System.Threading.Thread.GetDomain().DefineDynamicAssembly(assemblyName,
                                                                  System.Reflection.Emit.AssemblyBuilderAccess.
                                                                      RunAndSave);
    System.Reflection.Emit.ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(nameOfModule, nameOfDLL);
    System.Reflection.Emit.TypeBuilder typeBuilder = moduleBuilder.DefineType(nameOfType,
                                                                              System.Reflection.TypeAttributes.
                                                                                  Public |
                                                                              System.Reflection.TypeAttributes.Class);


    System.Reflection.Emit.FieldBuilder targetWrapedObjectField =
        typeBuilder.DefineField("_" + targetWrapType.FullName.Replace(".", ""), targetWrapType,
                                System.Reflection.FieldAttributes.Private);
    System.Reflection.MethodAttributes constructorAttributes = System.Reflection.MethodAttributes.Public;

    Type objType = Type.GetType("System.Object");
    System.Reflection.ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
    System.Reflection.Emit.ConstructorBuilder constructorBuilder =
        typeBuilder.DefineConstructor(constructorAttributes, System.Reflection.CallingConventions.Standard,
                                      new Type[] {targetWrapType});

    System.Reflection.Emit.ILGenerator ilConstructor = constructorBuilder.GetILGenerator();
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Call, objCtor);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Nop);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Stfld, targetWrapedObjectField);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Nop);
    ilConstructor.Emit(System.Reflection.Emit.OpCodes.Ret);


    System.Reflection.MethodAttributes propertyAttributes = System.Reflection.MethodAttributes.Public |
                                                            System.Reflection.MethodAttributes.HideBySig |
                                                            System.Reflection.MethodAttributes.SpecialName;

    foreach (var prop in targetObject.GetType().GetFields())
    {
        string Name = prop.Name;
        Type DataType = prop.FieldType;

        System.Reflection.Emit.PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(Name,
                                                                                            System.Reflection.
                                                                                                PropertyAttributes.
                                                                                                SpecialName,
                                                                                            DataType, null);
        System.Reflection.Emit.MethodBuilder methodBuilderGetter = typeBuilder.DefineMethod("get_" + Name,
                                                                                            propertyAttributes,
                                                                                            DataType, new Type[] {});
        System.Reflection.Emit.MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod("set_" + Name,
                                                                                            propertyAttributes,
                                                                                            typeof (void),
                                                                                            new Type[] {DataType});

        System.Reflection.Emit.ILGenerator ilGeneratorGetter = methodBuilderGetter.GetILGenerator();
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, prop);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ret);


        System.Reflection.Emit.ILGenerator ilGeneratorSetter = methodBuilderSetter.GetILGenerator();
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Stfld, prop);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ret);

        propertyBuilder.SetGetMethod(methodBuilderGetter);
        propertyBuilder.SetSetMethod(methodBuilderSetter);
    }


    System.Collections.Generic.List<System.Reflection.PropertyInfo> PropertieList = new List<PropertyInfo>();
    PropertieList.AddRange(targetObject.GetType().GetProperties(BindingFlags.Public));
    PropertieList.AddRange(targetObject.GetType().GetProperties(BindingFlags.NonPublic));

    foreach (var prop in PropertieList)
    {
        string Name = prop.Name;
        Type DataType = prop.PropertyType;

        System.Reflection.Emit.PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(Name,
                                                                                            System.Reflection.
                                                                                                PropertyAttributes.
                                                                                                SpecialName,
                                                                                            DataType, null);
        System.Reflection.Emit.MethodBuilder methodBuilderGetter = typeBuilder.DefineMethod("get_" + Name,
                                                                                            propertyAttributes,
                                                                                            DataType, new Type[] {});
        System.Reflection.Emit.MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod("set_" + Name,
                                                                                            propertyAttributes,
                                                                                            typeof (void),
                                                                                            new Type[] {DataType});

        System.Reflection.Emit.ILGenerator ilGeneratorGetter = methodBuilderGetter.GetILGenerator();
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Callvirt, prop.GetGetMethod());
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Stloc_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldloc_0);
        ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ret);


        System.Reflection.Emit.ILGenerator ilGeneratorSetter = methodBuilderSetter.GetILGenerator();
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, targetWrapedObjectField);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Callvirt, prop.GetSetMethod());
        ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ret);
        propertyBuilder.SetGetMethod(methodBuilderGetter);
        propertyBuilder.SetSetMethod(methodBuilderSetter);
    }

    // Yes! you must do this, it should not be needed but it is!
    Type dynamicType = typeBuilder.CreateType();

    // Save to file
    assemblyBuilder.Save(nameOfDLL);
    return dynamicType;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文