ILGenerator将属性添加到现有类型(仅生成私有字段

时间:2013-07-10 16:37:26

标签: .net reflection reflection.emit

我正在尝试撰写extension method,其中new type将返回名为type +个旧属性的所有属性ClosedDt。我现在得到了这个:

public static object GetDynamicObject(this System.Reflection.Emit.TypeBuilder typeBuilder,AssemblyName assembly, Type objectType)
    {
        AppDomain appDomain = System.Threading.Thread.GetDomain();
        AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);

        //create the class
        typeBuilder = moduleBuilder.DefineType(objectType.Name, TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass |
                                                            TypeAttributes.BeforeFieldInit, typeof(System.Object));
        foreach (var prop in objectType.GetProperties())
        {
            FieldBuilder fieldBuilder = typeBuilder.DefineField(prop.Name.Substring(0, 1).ToLower() + prop.Name.Substring(1),
                                                                prop.PropertyType, FieldAttributes.Private);
            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(prop.Name, PropertyAttributes.None,
                                                                         prop.PropertyType, new Type[]{prop.PropertyType});
            MethodBuilder propertyGetter = typeBuilder.DefineMethod("get_" + prop.Name, MethodAttributes.Public | MethodAttributes.HideBySig, prop.PropertyType, new Type[] { prop.PropertyType });
            var ilGenerator = propertyGetter.GetILGenerator();
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldfld,fieldBuilder);
            ilGenerator.Emit(OpCodes.Ret);

            MethodBuilder propertySetter = typeBuilder.DefineMethod("set_"+prop.Name, MethodAttributes.Public | MethodAttributes.HideBySig, prop.PropertyType, new Type[] { prop.PropertyType });
            var propertySetterIl = propertySetter.GetILGenerator();
            propertySetterIl.Emit(OpCodes.Ldarg_0);
            propertySetterIl.Emit(OpCodes.Ldarg_1);
            propertySetterIl.Emit(OpCodes.Stfld, fieldBuilder);
            propertySetterIl.Emit(OpCodes.Ret);
            propertyBuilder.SetGetMethod(propertyGetter);
            propertyBuilder.SetGetMethod(propertySetter);
        }

        FieldBuilder closedFieldBuilder = typeBuilder.DefineField("closedDt",
                                                                typeof(string), FieldAttributes.Private);
        PropertyBuilder closedPropertyBuilder = typeBuilder.DefineProperty("ClosedDt", PropertyAttributes.HasDefault,
                                                                     typeof(string), null);
        MethodBuilder closedPropertyGetter = typeBuilder.DefineMethod("get_ClosedDt", MethodAttributes.Public | MethodAttributes.SpecialName |
                                                                      MethodAttributes.HideBySig, typeof(string), Type.EmptyTypes);
        var ilGeneratorClosed = closedPropertyGetter.GetILGenerator();
        ilGeneratorClosed.Emit(OpCodes.Ldarg_0);
        ilGeneratorClosed.Emit(OpCodes.Ldfld, closedFieldBuilder);
        ilGeneratorClosed.Emit(OpCodes.Ret);

        MethodBuilder closedPropertySetter = typeBuilder.DefineMethod("set_ClosedDt", MethodAttributes.Public | MethodAttributes.SpecialName |
                                                        MethodAttributes.HideBySig, null, new Type[] { typeof(string) });
        var closedPropertySetterIl = closedPropertySetter.GetILGenerator();
        closedPropertySetterIl.Emit(OpCodes.Ldarg_0);
        closedPropertySetterIl.Emit(OpCodes.Ldarg_1);
        closedPropertySetterIl.Emit(OpCodes.Stfld, closedFieldBuilder);
        closedPropertySetterIl.Emit(OpCodes.Ret);
        closedPropertyBuilder.SetGetMethod(closedPropertyGetter);
        closedPropertyBuilder.SetGetMethod(closedPropertySetter);
        var dynamicType = typeBuilder.CreateType();
        return Activator.CreateInstance(dynamicType);
    }

对于记录:我知道如果我想在属性中添加一些属性,我需要从头开始创建新类。

但上面的代码只为private fields生成new type。 我错过了什么或我弄错了什么?

1 个答案:

答案 0 :(得分:1)

我猜你在DefineMethod调用getter和setter时缺少MethodAttributes.SpecialName。这个代码分叉,并正确创建getter。

    private static MethodBuilder BuildGetter(TypeBuilder typeBuilder, FieldInfo fieldBuilder, System.Reflection.Emit.PropertyBuilder propertyBuilder)
    {
        const MethodAttributes attributes = 
            MethodAttributes.Public | 
            MethodAttributes.HideBySig | 
            MethodAttributes.SpecialName | 
            MethodAttributes.Virtual |
            MethodAttributes.Final;

        var getterBuilder = typeBuilder.DefineMethod("get_" + propertyBuilder.Name, attributes, propertyBuilder.PropertyType, Type.EmptyTypes);

        // Code generation
        var ilgen = getterBuilder.GetILGenerator();

        ilgen.Emit(OpCodes.Ldarg_0);
        ilgen.Emit(OpCodes.Ldfld, fieldBuilder); // returning the firstname field
        ilgen.Emit(OpCodes.Ret);
        return getterBuilder;
    }