It's a well know rule that the readonly fields can only be set in the static constructors or auto constructors. But if we just have a requirement to set it outside the constructors, can this really be done?
The answer is yes, we can crack it by using Reflection. Actually, we can get the FieldInfo which is a wrapper class which contains all the information related to a field, and it exposes SetValue interface to us which we can leverage.
Suppose we have the following Person type:
public class Person
{
private int age;
private string sex;
readonly private static string name;
readonly private string job;
static
Person()
{
name = "initial
name";
}
public
Person()
{
age = 10;
sex = "male";
job = "none";
}
public int Age
{
get
{
return
age;
}
}
public string Job
{
get
{
return
job;
}
}
public static string Name
{
get
{
return
name;
}
}
public string Sex
{
get
{
return
sex;
}
}
}
We can see that there's a static constructor and an auto constructor giving initial values for the fields, now in a consumption code, we may write the following code:
public void Main()
{
Person p
= new Person();
Console.WriteLine(p.Job);
Console.WriteLine(Person.Name);
Console.WriteLine(p.Age);
Type
type = p.GetType();
FieldInfo
nameField = type.GetField("name", BindingFlags.NonPublic | BindingFlags.Static);
nameField.SetValue(null,
"NewName");
FieldInfo
jobField = type.GetField("job", BindingFlags.NonPublic | BindingFlags.Instance);
jobField.SetValue(p, "New Job");
FieldInfo
ageField = type.GetField("age", BindingFlags.NonPublic | BindingFlags.Instance);
ageField.SetValue(p, 20);
Console.WriteLine(p.Job);
Console.WriteLine(Person.Name);
Console.WriteLine(p.Age);
}
With this, we can also see that the trick used above can also be applied in cracking the private field.
Sometimes, when we are using components by others, we may have less control with it. So knowing this trick will help you in handling certain type of cases.
By the way, if we don't know the declaration of the fields or methods, we can get it through Object Browser of Visual Studio.