1

I have this class, defined in one of .NET's framework assemblies:

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

I derive from ExternalClass and would like to either override or somehow intercept calls to that property. I'm aware that this can get very hacky, but it's really only for a proof-of-concept.

I tried the straightforward way with reflection, but haven't had any luck:

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

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

From 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);
}

Is there a way to do this with reflection, or any other method with reasonable small effort? I can (properly) work around this for my actual problem, so a "No" is really an acceptable answer, but I'm curious if this would be possible.

Lennart
  • 9,657
  • 16
  • 68
  • 84
  • You just need a setter in the base property class. `private double _desiredProperty = 1.0` `internal double DesiredProperty {get => _desiredProperty; set => _desiredProperty = value;}` – Nekeniehl Jul 02 '18 at 09:18
  • You might be able to intercept the call using something like Typemock Isolator (you would need essential edition or above). – John Wu Jul 02 '18 at 09:51

1 Answers1

4
internal double DesiredProperty => 1.0;

Declares the property to have a lambda expression body. This compiles into a method that happens to always return 1.0. You can't change what value this method will return since that won't be stored anywhere outside of that method's IL. There is no "backing field" which is what your second code example seems to be looking for.

E.g. if you compile this code, this is what's emitted:

.method assembly hidebysig specialname instance float64 get_DesiredProperty() cil managed
{
    .maxstack 8
    L_0000: ldc.r8 1
    L_0009: ret 
}
Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Thanks, that's what I expected. The property is actually a regular getter that returns a constant value (I only used a lambda expression to make the example shorter), but the emitted IL code is exactly the same as the one you posted. – Lennart Jul 03 '18 at 06:30