Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing read only properties with reflection

Tags:

c#

reflection

Is it possible? With reflection or any other way?

like image 912
Élodie Petit Avatar asked Sep 14 '10 05:09

Élodie Petit


People also ask

How do I change the readonly property?

You can use mapping modifiers to change a readonly property to mutable in TypeScript, e.g. -readonly [Key in keyof Type]: Type[Key] . You can remove the readonly modifier by prefixing the readonly keyword with a minus - .

Can we change read only value in C#?

The readonly keyword can be used to define a variable or an object as readable only. This means that the variable or object can be assigned a value at the class scope or in a constructor only. You cannot change the value or reassign a value to a readonly variable or object in any other method except the constructor.

What are the properties of read only?

Read only means that we can access the value of a property but we can't assign a value to it. When a property does not have a set accessor then it is a read only property. For example in the person class we have a Gender property that has only a get accessor and doesn't have a set accessor.

How do you know if a property is readonly?

With PropertyDescriptor , check IsReadOnly . With PropertyInfo , check CanWrite (and CanRead , for that matter). You may also want to check [ReadOnly(true)] in the case of PropertyInfo (but this is already handled with PropertyDescriptor ): ReadOnlyAttribute attrib = Attribute.


3 Answers

As other stated, if you need to do that, you're facing a design issue to begin with. Now, if you want to know if it's possible just for the sake of knowing, or if there's no other way on earth to do it, it's indeed possible, with the help of a very small helper library and an extension method.

Consider the following code:

class Person {      int age;     string name;      public int Age { get { return age; } }     public string Name { get { return name; } } }  // ...  using Mono.Reflection; using System.Reflection;  // ...  Person person = new Person (27, "jb"); PropertyInfo nameProperty = typeof (Person).GetProperty ("Name"); FieldInfo nameField = nameProperty.GetBackingField (); nameField.SetValue (person, "jbe"); 

Using this code, you can get the backing field of a property with just the property, and assign a new value to the backing field. You can read more details about the implementation.

Also note that it works only for simple properties, such as:

public int Age { get { return age; } }  public string Name {     get { return name; }     set { name = value; } }  public double Velocity { get; private set; } 

If you have complex properties with custom code (which includes expression-bodied member like int Answer=> 42;), the backing field resolver will fail as there is no backing field in such case.

like image 163
Jb Evain Avatar answered Sep 20 '22 08:09

Jb Evain


An alternate to Simon Mattes answer would be

Assuming you have:

public class MyClass {      public int MyNumber {get;} } 

You could do this if its for test purpose:

var field = typeof(MyClass).GetField("<MyNumber>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); field.SetValue(anIstanceOfMyClass, 3); 
like image 39
Abyte0 Avatar answered Sep 20 '22 08:09

Abyte0


As a very dirty workaround for auto generated read only properties:

class MyTestClass
{
    public string MyProperty { get; }

    public MyTestClass( string MyProperty )
    {
        this.MyProperty = MyProperty;
    }
}

You can modify the auto generated backing field in the following way:

MyTestClass MyClass = new MyTestClass( "Hello" );
FieldInfo MyWriteableField = MyClass.GetType().GetRuntimeFields().Where( a => Regex.IsMatch( a.Name, $"\\A<{nameof( MyClass.MyProperty )}>k__BackingField\\Z" ) ).FirstOrDefault();
MyWriteableField.SetValue( MyClass, "Another new value" );

PS: when you are using a .NET version < 4.6 you might have to change some of the code to work. Enjoy!

like image 20
Simon Mattes Avatar answered Sep 22 '22 08:09

Simon Mattes