Changing Read Only Properties with Reflection

Changing read only properties with reflection

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.

Set readonly property value through reflection

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);

Skipping properties that are read-only when setting using reflection

you could try to check the CanWrite property:

    class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();

foreach (PropertyInfo property in demo.GetType().GetProperties())
{
if (property.CanWrite)
{
property.SetValue(demo, "New value");
}
}
}
}

public class Demo
{
public string ReadOnlyProperty { get; }

public string ReadWriteProperty { get; set; }
}

Best regards

Modify collection items using reflection?

readonly only applies to the field and means that you cannot assign it another (or the same) collection instance or null. It does not mean that the collection itself is a read-only collection.

Since you have a variable myCollection typed as List<string>, you do not need Reflection. Just write

myCollection.Add("some value"); // allowed.

Note that a List<T> is a class and therefore a reference type. I.e., the variable myCollection contains a reference to the real collection. myCollection.Add("some value"); adds the new value to the real collection (MyAssembly.Constants.MyCollection)!

But something like Constants.MyCollection = null; is not allowed because of the readonly keyword.

Example:

static readonly List<string> myCollection = new List<string>();
static ReadOnlyCollection<string> roc = new ReadOnlyCollection<string>(myCollection);

readonly fields or properties can be initialized with an initializer expression or in a constructor. Given the declarations above:

myCollection.Add("text"); // OK, collection not readonly.
myCollection = new List<string>(); // NOT POSSIBLE, field readonly.

roc.Add("text"); // NOT POSSIBLE, readonly collection has no Add method.
roc = new ReadOnlyCollection<string>(new[] { "a", "b" }); // OK, roc field not readonly.

static does not mean that the field or collection cannot be changed. It means that the field is not an instance field that must be referenced through a class instance (an object), rather, it belongs to the class and can be accessed through the class name.

Example:

class MyClass
{
public static int staticField;
public int instanceField;
}

Given the declaration above:

var obj = new MyClass();
var x = obj.instanceField; // OK
var y = MyClass.staticField; // OK

var z = MyClass.instanceField; // DOES NOT COMPILE!
// CS0120: An object reference is required for the nonstatic field, method, or property
// 'MyClass.instanceField'

var t = obj.staticField; // DOES NOT COMPILE!
// CS0176: Static member 'MyClass.staticField' cannot be accessed with an instance
// reference; qualify it with a type name instead

Can I change a private readonly field in C# using reflection?

You can:

typeof(Foo)
.GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic)
.SetValue(foo,567);

Change .NET Property Grid readonly attribute at runtime

Yes! This could be helpful!

public class Member
{
string name;
bool isMarried;
string spouseName;

public string Name
{
get { return name; }
set { name = value; }
}

[System.ComponentModel.RefreshProperties(RefreshProperties.All)]
public bool IsMarried
{
get { return isMarried; }
set
{
isMarried = value;
bool newValue = !value;
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())["SpouseName"];
ReadOnlyAttribute attrib = (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];
FieldInfo isReadOnly = attrib.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
isReadOnly.SetValue(attrib, newValue);
}
}

[ReadOnly(true)]
public string SpouseName
{
get { return spouseName; }
set
{
spouseName = value;
}
}
}


Related Topics



Leave a reply



Submit