【问题标题】:Overriding an internal get-only property from a base class覆盖基类的内部 get-only 属性
【发布时间】:2018-12-10 11:26:48
【问题描述】:

我有这个类,在 .NET 的一个框架程序集中定义:

public class ExternalClass
{    
   internal double DesiredProperty => 1.0;    
}

我从 ExternalClass 派生并希望覆盖或以某种方式拦截对该属性的调用。我知道这可能会变得非常棘手,但这实际上只是为了概念验证。

我尝试了反射的直接方法,但没有任何运气:

 private void DoEvilStuff()
    {
        var prop = typeof(ExternalClass).GetProperty("DesiredProperty", BindingFlags.Instance | BindingFlags.NonPublic);

        // Exception: Property has no setter
        prop.SetValue(this, 5);
    }

来自another answer:

private void DoEvilStuff()
{
    var prop = typeof(ExternalClass).GetField("<DesiredProperty>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);

    // fails, prop is null:
    prop.SetValue(this, 5);
}

有没有办法通过反射来做到这一点,或者任何其他合理的小努力方法?对于我的实际问题,我可以(适当地)解决这个问题,所以“否”确实是一个可以接受的答案,但我很好奇这是否可能。

【问题讨论】:

  • 您只需要在基础属性类中设置一个设置器。 private double _desiredProperty = 1.0internal double DesiredProperty {get =&gt; _desiredProperty; set =&gt; _desiredProperty = value;}
  • 您可能可以使用 Typemock Isolator 之类的工具拦截呼叫(您需要基本版或更高版本)。

标签: c# reflection


【解决方案1】:
internal double DesiredProperty => 1.0;

声明属性具有 lambda 表达式主体。这编译成一个方法,它恰好总是返回1.0。您无法更改此方法将返回的值,因为它不会存储在该方法的 IL 之外的任何位置。您的第二个代码示例似乎正在寻找没有“支持字段”。

例如如果你编译这段代码,这就是发出的:

.method assembly hidebysig specialname instance float64 get_DesiredProperty() cil managed
{
    .maxstack 8
    L_0000: ldc.r8 1
    L_0009: ret 
}

【讨论】:

  • 谢谢,这正是我所期望的。该属性实际上是一个返回常量值的常规 getter(我只使用了 lambda 表达式来使示例更短),但发出的 IL 代码与您发布的完全相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-05
  • 2019-10-13
  • 2023-03-13
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
相关资源
最近更新 更多