【问题标题】:Dynamically get value from overriden property从被覆盖的属性中动态获取值
【发布时间】:2015-11-21 05:18:01
【问题描述】:

我希望能够在运行时使用反射动态获取覆盖属性的值。例如,

class A {
    public virtual int Foo => 5;

    //This implementation doesn't work
    public int ParentFoo => (int)this.GetType().BaseType.GetProperty(nameof(Foo)).GetValue(this); 
}

class B : A {
    public override int Foo => 7;
}

var test = new B();
Console.WriteLine(test.Foo);       //"7"
Console.WriteLine(test.ParentFoo); //Should display "5"

这样做的重点是类型层次结构相当深,我不希望扩展程序每次都必须使用完全相同的逻辑 (public int ParentFoo => base.Foo;) 重新实现 ParentFoo。我不介意为反射支付性能成本——这个属性不需要是高性能的。

是否可以使用反射来完成我这里需要的事情?

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

    可以始终使用反射调用属性的原始定义类的方法。这是一个坏主意。下面的代码说明了这个概念,但不值得战斗,也不应该变得值得战斗。

    void Main()
    {
        var a = new A();
        Console.WriteLine(GetNoVCall<A, int>(a, z => z.Foo)); // prints 5
        var b = new B();
        Console.WriteLine(GetNoVCall<A, int>(b, z => z.Foo)); // prints 5
        Console.WriteLine(GetNoVCall<B, int>(b, z => z.Foo)); // prints 5
    }
    
    class A
    {
        public virtual int Foo { get { return 5; } }
    }
    
    class B : A
    {
        public override int Foo { get { return 7; } }
    }
    
    public static TProp GetNoVCall<TClass, TProp>(TClass c, Expression<Func<TClass, TProp>> f)
    {
        var expr = f.Body as MemberExpression;
        var prop = expr.Member as PropertyInfo;
        var meth = prop.GetGetMethod(true);
        var src = expr.Expression as ParameterExpression;
    
        if (src == null || prop == null || expr == null)
            throw new Exception();
    
        var dyn = new DynamicMethod("GetNoVCallHelper", typeof(TProp), new Type[]{ typeof(TClass) }, typeof(string).Module, true);
        var il = dyn.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Call, meth);
        il.Emit(OpCodes.Ret);
    
        return ((Func<TClass, TProp>)dyn.CreateDelegate(typeof(Func<TClass, TProp>)))(c);
    }
    

    【讨论】:

    • 我同意@user5090812。如果您需要这两个值,请为这两个值设置单独的属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2013-01-19
    • 2015-07-07
    相关资源
    最近更新 更多