Can I change a private readonly field in C# using reflection?
Solution 1:
You can:
typeof(Foo)
.GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic)
.SetValue(foo,567);
Solution 2:
The obvious thing is to try it:
using System;
using System.Reflection;
public class Test
{
private readonly string foo = "Foo";
public static void Main()
{
Test test = new Test();
FieldInfo field = typeof(Test).GetField
("foo", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(test, "Hello");
Console.WriteLine(test.foo);
}
}
This works fine. (Java has different rules, interestingly - you have to explicitly set the Field
to be accessible, and it will only work for instance fields anyway.)
Solution 3:
I agree with the other answers in that it works generally and especially with the comment by E. Lippert that this is not documented behavior and therefore not future-proof code.
However, we also noticed another issue. If you're running your code in an environment with restricted permissions you might get an exception.
We've just had a case where our code worked fine on our machines, but we received a VerificationException
when the code ran in a restricted environment. The culprit was a reflection call to the setter of a readonly field. It worked when we removed the readonly restriction of that field.
Solution 4:
You asked why you would want to break the encapsulation like that.
I use an entity helper class to hydrate entities. This uses reflection to get all the properties of a new empty entity, and matches the property/field name to the column in the resultset, and set's it using propertyinfo.setvalue().
I don't want anyone else to be able to change the value, but I don't want to take all the effort to custom code hydration methods for every entity either.
My many of my stored procs return resultsets that don't correspond directly to tables or views, so the code gen ORM's do nothing for me.