-1

I need to modify a property value which has only "get" option. I have found some trick with using GetField but I did not succeed.

See below the code:

namespace ConsoleApplication1
{
  abstract class Test
  {
    private int testValue;
    protected int TestValue {
        get { return testValue; }
    }
  }
  class Myclass : Test
  {
    public Myclass(): base(){}
  }  

  class Program
  {
    static void Main(string[] args)
    {
      Myclass test = new Myclass();

      var field = typeof(Myclass).GetField("<TestValue>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance);
      field.SetValue(test, 3);

    }
  }
}

Actually, I would like to set "TestValue" with a the value 3 but it is not working. I do probably something wrong.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
Zaraki21
  • 21
  • 1
  • 4
  • Obvious question is... **why**? Yes, you might do it getting the field (check binding flags and exact name) but that's a nasty implementation detail which may change with the next build! Do you own that code? Make setter public. You don't own that code? Post a question asking how to circumvent that (with a relevant example, of course). BTW that's the problem with hypothetical code...in your example it's `testValue` not `k_BackingField` – Adriano Repetti Aug 30 '17 at 08:30
  • Couldn't you just add a setter for the prototype and then delete it afterwards? – Pezo Aug 30 '17 at 08:31
  • 3
    Possible duplicate of [how to implement a read only property](https://stackoverflow.com/questions/3917796/how-to-implement-a-read-only-property) – SpacemanSpiff Aug 30 '17 at 08:31
  • _"it is not working"_ - read [ask] and explain how exactly it isn't working and what you've tried to get it to work. – CodeCaster Aug 30 '17 at 08:32
  • 1
    @SpacemanSpiff no, that is not at all what is being asked here. – CodeCaster Aug 30 '17 at 08:35
  • Possible duplicate of [Reflecting a private field from a base class](https://stackoverflow.com/questions/6961781/reflecting-a-private-field-from-a-base-class) – Mong Zhu Aug 30 '17 at 08:38
  • Possible duplicate of [How to set value of property where there is no setter](https://stackoverflow.com/questions/20665410/how-to-set-value-of-property-where-there-is-no-setter) – George Hanna Aug 30 '17 at 08:42
  • You cannot set a property without a setter (I mean TestValue). But of course you can set the variable testValue. You can do it with reflection, constructor or with a public method. – HGMamaci Aug 30 '17 at 08:47
  • Possible duplicate of [Changing read only properties with reflection](https://stackoverflow.com/questions/3706389/changing-read-only-properties-with-reflection) – Frédéric Dec 07 '17 at 11:38

3 Answers3

2

The "trick" you found relies on auto-implemented properties (string Foo { get; }) that compile into a property with a backing field (hence the name of the member you're looking up). Do note that this is extremely fragile, as the generated member name isn't documented. But hey, relying on reflection to access a type's members is fragile to begin with.

You don't have an auto-implemented property though, you just need to access the private field named testValue which the property exposes.

But GetField() doesn't deal with inheritance for nonpublic members, so see GetFields of derived type. This method will help with that:

public static void Main()
{
    Myclass test = new Myclass();

    var field = GetInheritedPrivateField(test.GetType(), "testValue");

    field.SetValue(test, 3);
}

private static FieldInfo GetInheritedPrivateField(Type type, string fieldName)
{
    do
    {
        var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

        if (field != null)
        {
            return field;
        }

        type = type.BaseType;
    } 
    while (type != null);

    return null;
}
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
1

You can retrieve the field info for the Test class and use it to set the value on the derived class instance like so:

var field = typeof(Test).GetField("testValue", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(test, 3);
Mihai Pantea
  • 360
  • 3
  • 8
  • Thanks for the tip, it works but if I have only a "Get" property without any field it is not working. do you have any solution for that ? For example, in my case, I have only protected int TestValue { get; } – Zaraki21 Aug 30 '17 at 09:12
  • Forget my last comment, I use your tip and it solved my problem. Thank you. – Zaraki21 Aug 30 '17 at 13:18
-1

You cannot set a value on property without a "setter".

If you don't want the property to be overridden by some other object outside the scope, you might use "private set" as setter, then you may set the value within the scope.

Another approach would be to write a method to set the value of the getter of your property. i.e.

 class Myclass : Test
  {
    public Myclass(): base(){}

    public void SetValue(int value) { this.testValue=value; }
  }  
HGMamaci
  • 1,339
  • 12
  • 20
  • 1
    You can, with reflection. – CodeCaster Aug 30 '17 at 08:34
  • You can set a value *without* a `setter`, for example with the constructor – Filnor Aug 30 '17 at 08:35
  • Then look at better. You cannot set a property without a setter (I mean TestValue). But of course you can set the variable testValue. - Which tells me before downvoting someone, read carefully. – HGMamaci Aug 30 '17 at 08:45
  • If a property exposes a field, you can set the field's value and therefore indirectly affect the property's value. You also can't set an inherited private field with `this.field = value`. So before answering, read the question carefully. – CodeCaster Aug 30 '17 at 08:48
  • But still not the exact answer, and does not clear a beginner's head for example, how it works. And still - does not justify your downvoting. Anyway - good luck – HGMamaci Aug 30 '17 at 08:49