使用Reflection.Emit覆盖属性定义 [英] Overriding property definitions with Reflection.Emit

查看:40
本文介绍了使用Reflection.Emit覆盖属性定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Reflection.Emit(TypeBuilder)实现此模式:

I'm trying to implement this pattern using Reflection.Emit (TypeBuilder):

public class ClassToBeProxied
{
    public virtual object Property1 { get; set; }
}

public class Proxy : ClassToBeProxied
{
    [AttributeToBeAdded]
    public override object Property1
    {
        get
        {
            //do something else to return the object - i.e get it from the database
            return null; //stub
        }
        set
        {
            //do something else to set the object - i.e, save it to a database
        }
    }        
}

如果我所做的只是拦截get和set方法,那么它将起作用:

If all I were doing was intercepting the get and set methods, then this works:

PropertyInfo info = typeof(ClassToBeProxied).GetProperty("Property1", BindingFlags.Public | BindingFlags.Instance);
{
    MethodBuilder pGet = typeBuilder.DefineMethod("get_" + info.Name, MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, info.PropertyType, Type.EmptyTypes);
    ILGenerator pILGet = pGet.GetILGenerator();

    //The proxy object
    pILGet.Emit(OpCodes.Ldarg_0);
    //The database
    pILGet.Emit(OpCodes.Ldfld, database);
    //The proxy object
    pILGet.Emit(OpCodes.Ldarg_0);
    //The ObjectId to look for
    pILGet.Emit(OpCodes.Ldfld, f);
    pILGet.Emit(OpCodes.Callvirt, typeof(MongoDatabase).GetMethod("Find", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ObjectId) }, null).MakeGenericMethod(info.PropertyType));
    pILGet.Emit(OpCodes.Ret);

    MethodBuilder pSet = typeBuilder.DefineMethod("set_" + info.Name, MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new Type[] { info.PropertyType });
    ILGenerator pILSet = pSet.GetILGenerator();
    pILSet.Emit(OpCodes.Ldarg_0);
    pILSet.Emit(OpCodes.Ldarg_1);
    pILSet.Emit(OpCodes.Ldarg_0);
    pILSet.Emit(OpCodes.Ldfld, database);
    pILSet.Emit(OpCodes.Call, typeof(ProxyBuilder).GetMethod("SetValueHelper", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object), typeof(MongoDatabase) }, null));
    pILSet.Emit(OpCodes.Stfld, f);
    pILSet.Emit(OpCodes.Ret);

    //Edit:  Added fix
    newProp.SetSetMethod(pSet);
    newProp.SetGetMethod(pGet);
}

但是我还需要向属性添加一个属性.我不知道该怎么做.

But what I need to do is also add an attribute to the Property. I can't figure out how to do this.

如果我添加新的PropertyDefinition:

If I add a new PropertyDefinition:

PropertyBuilder newProp = typeBuilder.DefineProperty(info.Name, PropertyAttributes.None, info.PropertyType, Type.EmptyTypes);
newProp.SetCustomAttribute(new CustomAttributeBuilder(typeof(AttributeToBeAdded).GetConstructor(Type.EmptyTypes), Type.EmptyTypes, new FieldInfo[0], new object[0]));

,然后在生成的类型上调用GetProperties(),将出现两个具有相同名称的属性.但是,如果我手动构建代码(如上例所示),并调用typeof(Proxy).GetProperties(),则只有一个Property(派生类属性)可见.这是我所需要的行为,但是我似乎无法使用Reflection.Emit

and then call GetProperties() on the generated type, two properties with the same name appear. However, if I build the code by hand (as in the example above), and call typeof(Proxy).GetProperties(), only one Property (the derived class property) is visible. This is the behavior I need, but I can't seem to get there with Reflection.Emit

请让我知道是否需要添加更多信息以使问题更清楚.

Please let me know if I need to add more info to make the question clearer.

推荐答案

所以答案是这样的:

newProp.SetSetMethod(pSet);
newProp.SetGetMethod(pGet);

查看已编辑的问题.

答案种类矛盾 http://www.gutgames.com/post/Overridding-a-Property-With-ReflectionEmit.aspx

但似乎可行.

这篇关于使用Reflection.Emit覆盖属性定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆