使用reflection - base.Property而不是this.Property获取baseclass属性值

时间:2011-07-15 19:55:23

标签: c# reflection properties

我想知道这样的事情是否可行:我已经覆盖了基类的属性,它是自动实现的。我在覆盖中提供了逻辑,以解决默认设置下的“缺失”属性。

现在,我想使用反射来检查是使用默认值还是某些“实际”值。换句话说,我需要检查base.Property是否为null,但是使用反射。这不起作用,它只是获取子类值(根据默认值解析,因此不为null)。

var property = this.GetType().GetProperty(e.PropertyName);
if(property.GetValue(this, null) == null))
    OnPropertyChanged(e.PropertyName);

也尝试过:

var property = this.GetType().BaseType.GetProperty(e.PropertyName);
if(property.GetValue(this, null) == null))
    OnPropertyChanged(e.PropertyName);

是否可以使用反射来访问基类值?

更新:

根据评论的建议,我尝试了以下内容,仅仅是为了解决问题。

var method1 = this.GetType().BaseType.GetMethods().First(x => x.Name.Contains(e.PropertyName));
var method = this.GetType().BaseType.GetProperty(e.PropertyName).GetGetMethod();
var methodValue = method1.Invoke(this, null);

这两个仍然返回“派生”值,而同时base.Property返回null。

2 个答案:

答案 0 :(得分:5)

虽然据我所知,如果没有发出自己的IL,就没有办法做到这一点,基本上使用call指令而不是callvirt

请注意,如果您需要使用这些长度来使您的设计工作,那么这表明您可能在某处做错了!

无论如何,这是一个人为的例子。 (为简洁起见,省略了错误检查等。)

var derived = new DerivedClass();
Console.WriteLine(derived.GetBaseProperty("Prop"));    // displays "BaseProp"

// ...

public class BaseClass
{
    public virtual string Prop { get; set;}
}

public class DerivedClass : BaseClass
{
    public override string Prop { get; set;}

    public DerivedClass()
    {
        base.Prop = "BaseProp";
        this.Prop = "DerivedProp";
    }

    public object GetBaseProperty(string propName)
    {
        Type t = this.GetType();
        MethodInfo mi = t.BaseType.GetProperty(propName).GetGetMethod();

        var dm = new DynamicMethod("getBase_" + propName, typeof(object), new[] { typeof(object) }, t);

        ILGenerator il = dm.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Call, mi);
        if (mi.ReturnType.IsValueType) il.Emit(OpCodes.Box, mi.ReturnType);
        il.Emit(OpCodes.Ret);

        var getBase = (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));
        return getBase(this);
    }
}

答案 1 :(得分:1)

AFAIK我认为这是不可能的。对象的真实类型是派生类型,并且根据虚拟方法的定义,无论您通过哪种类型实例(实际类型或基本类型)调用方法,你将获得覆盖的实现。

以任何其他方式完成这项工作对我来说至少是出乎意料的行为。

编辑:我尝试了以下内容,看看是否有可能进入基础实施:

Type baseType = this.GetType().BaseType;
var methodInfo = baseType.GetMethod("Foo");
string foo = methodInfo.Invoke(this, null); //Derived type implementation

这意味着即使通过base类型MethodInfo反射调用该方法也能够解析覆盖并返回派生的实现。所以我认为你所尝试的是不可能通过反思或者至少我看不到这样做的方法。