C# 使用reflection-base.property而不是this.property获取基类属性值

C# 使用reflection-base.property而不是this.property获取基类属性值,c#,reflection,properties,C#,Reflection,Properties,我想知道这样的事情是否可行:我已经重写了基类的一个属性,它是自动实现的。我在覆盖中提供了逻辑,以根据默认设置解决“缺失”属性 现在,我想使用反射来检查是使用默认值还是某些“实际”值。换句话说,我需要检查base.Property是否为null,但要使用反射。这不起作用,它只是获取子类值(根据默认值进行解析,因此不为null) 还尝试: var property = this.GetType().BaseType.GetProperty(e.PropertyName); if(property.G

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

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

还尝试:

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。

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

至少对我来说,以任何其他方式完成这项工作都是意想不到的行为

编辑:我尝试了以下方法,看看是否真的有可能实现基本实现:

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

这意味着,即使通过
base
type
MethodInfo
反射调用该方法,也能够解决覆盖问题,并返回派生的实现。因此,我认为你所尝试的是不可能通过反射实现的,或者至少我看不到一种实现的方法。

这是可能的,尽管据我所知,如果不发出你自己的IL,基本上是使用指令而不是命令,是无法实现的

请注意,如果您需要进行这些工作,以使您的设计工作,那么这是一个迹象,表明您可能正在做一些错误的地方

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

var-derived=new-DerivedClass();
Console.WriteLine(派生的.GetBaseProperty(“Prop”);//显示“BaseProp”
// ...
公共类基类
{
公共虚拟字符串属性{get;set;}
}
公共类派生类:基类
{
公共重写字符串Prop{get;set;}
公共类()
{
base.Prop=“BaseProp”;
this.Prop=“DerivedProp”;
}
公共对象GetBaseProperty(字符串propName)
{
Type t=this.GetType();
MethodInfo mi=t.BaseType.GetProperty(propName).GetMethod();
var dm=newdynamicmethod(“getBase_”+propName,typeof(object),new[]{typeof(object)},t);
ILGenerator il=dm.GetILGenerator();
il.Emit(操作码.Ldarg_0);
发射(操作码呼叫,mi);
if(mi.ReturnType.IsValueType)il.Emit(操作码.Box,mi.ReturnType);
发射(操作码Ret);
var getBase=(Func)dm.CreateDelegate(typeof(Func));
返回getBase(this);
}
}

From MSDN:请注意,您不能使用基类中的MethodInfo对象调用派生类中被重写的方法,因为后期绑定无法解析重写。@JeffN825:我想我在这一点上可能是错的,但是我会保留答案,因为我仍然需要测试它是否真的可能,这是我真的不喜欢的一个特性。通过派生类型访问基实现在某种程度上破坏了派生类型实现,谁知道会产生什么结果。无论如何,反射的缺点之一是它允许你做你不能做的事情,但我们可以接受它,因为它非常有用:p。我只是希望,在这种情况下,我的答案是正确的。是的,我明白你的意思,但使用base.Property是可能的,所以我认为可能也有一些反映忍者的方法。@Max:我可能在这一点上错了。试试JeffN825所说的,似乎它应该能起作用。@在两者之间,我会的。但我明白你的意思,这不是一个非常干净的方法。但我可以看到的另一种透明方式是跟踪设置了哪些属性,即保留一个需要大量代码的字典/索引…@Tigran是的,否则我无法覆盖它,对吗?你可以使用“new”,这取决于…@Tigran哦,是的,对。但是当我把这个类作为它的基类传递时,我希望这些属性被正确地覆盖。我尝试了不同的方法,老实说,在我看来这是不可能的。可能是为了识别默认值,最好有公共静态字段来描述每个属性的每个默认值,以便您可以在需要时进行比较。“但你为什么要用反射来做这件事呢?”蒂格兰说,“不,看起来不是这样,根据其他答案也不是这样。这本来是一种方便的检查值是“设置”还是“默认”的方法,尽管很难看,但感谢您提供的信息,但正如您正确地说的,需要这样做可能表明您在设计中的某个地方犯了错误;)。这让我有点放心,因为它不是那么简单,这只是因为你没有支持领域。您只需存储两个文本。OP指定base属性是自动实现的。@Charles:Oops,这就是我在睡眠不足(也没有正确测试)的情况下编写这样的代码所得到的。希望现在可以修复,并且我已经更新了示例,使其也可以使用自动属性。
Type baseType = this.GetType().BaseType;
var methodInfo = baseType.GetMethod("Foo");
string foo = methodInfo.Invoke(this, null); //Derived type implementation
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);
    }
}