C# : modificare un campo readonly ? Si può con la Reflection !
Tutti sappiamo che definendo il campo di una classe con la keyword readonly, quest’ultimo assumerà un valore a runtime che potrà essere assegnato solo ed esclusivamente nel costruttore della classe ma non potrà più essere modificato successivamente.
Ad esempio, consideriamo la definizione della seguente classe :
1: public class MyClass
2: {
3: private readonly int rField;
4:
5: public MyClass(int field)
6: {
7: this.rField = field;
8: }
9:
10: public int RField
11: {
12: get
13: {
14: return this.rField;
15: }
16: set
17: {
18: this.rField = value;
19: }
20: }
21: }
Se proviamo a compilare tale classe, il compilatore restituirà il seguente errore :
A readonly field cannot be assigned to (except in a constructor or a variable initializer)
Attraverso la Reflection è invece possibile modificare un campo definito readonly in un qualsiasi momento dell’esecuzione.
Per fare questo, bisogna modificare il set della property RField nel modo seguente :
1: set
2: {
3: this.GetType()
4: .GetField("rField", BindingFlags.NonPublic | BindingFlags.Instance)
5: .SetValue(this, value);
6: }
Utilizzando la Reflection, si accede al campo readonly rField e se ne modifica il valore.
In questo modo, non otteniamo alcun errore di compilazione ed eseguendo il seguente programma di test :
1: static void Main(string[] args)
2: {
3: MyClass myClass = new MyClass(10);
4: Console.WriteLine("MyClass.RField = {0} after ctor", myClass.RField);
5: myClass.RField = 5;
6: Console.WriteLine("MyClass.RField = {0} after setting property", myClass.RField);
7: }
otteniamo il seguente output :

dal quale si evince che il campo readonly è stato modificato !
Hacking su un campo private e readonly
Andando oltre il semplice esempio didattico suddetto, questa tecnica si potrebbe utilizzare per eseguire un hacking su un campo privato readonly di una classe. Supponiamo che la classe suddetta sia di questo tipo :
1: public class MyClass
2: {
3: private readonly int rField;
4:
5: public MyClass(int field)
6: {
7: this.rField = field;
8: }
9:
10: public int RField
11: {
12: get
13: {
14: return this.rField;
15: }
16: }
17: }
Il campo rField non è accessibile dall’esterno (private), non è modificabile a runtime (readonly) e la relativa property RField ne permette esclusivamente la lettura (get). Sfruttando però la Reflection con la tecnica vista prima, possiamo comunque modificare il campo nel modo seguente :
1: static void Main(string[] args)
2: {
3:
4: MyClass myClass = new MyClass(10);
5: Console.WriteLine("MyClass.RField = {0} after ctor", myClass.RField);
6: myClass.GetType()
7: .GetField("rField", BindingFlags.NonPublic | BindingFlags.Instance)
8: .SetValue(myClass, 5);
9: Console.WriteLine("MyClass.RField = {0} after setting property", myClass.RField);
10:
11: }
che in esecuzione darà il seguente output :

A tutti gli effetti abbiamo eseguito un hacking su un campo che era stato previsto non accessibile in scrittura e non modificabile dallo sviluppatore !