Cambiar las propiedades de solo lectura con reflexión

¿Es posible? Con reflexión o de otra manera?

Como dice otro, si necesita hacer eso, se enfrenta a un problema de diseño, para empezar. Ahora, si quieres saber si es posible solo por el hecho de saberlo, o si no hay otra manera en la tierra para hacerlo, de hecho es posible, con la ayuda de una pequeña biblioteca auxiliar y un método de extensión.

Considera el siguiente código:

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

Con este código, puede obtener el campo de respaldo de una propiedad con solo la propiedad y asignarle un nuevo valor al campo de respaldo. Puede leer más detalles sobre la implementación .

También tenga en cuenta que solo funciona para propiedades simples, como:

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

Si tiene propiedades complejas con código personalizado, la resolución del campo de respaldo fallará.

Como una solución muy sucia para las propiedades de solo lectura generadas automáticamente:

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

Puede modificar el campo de respaldo generado automáticamente de la siguiente manera:

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

PD: cuando está utilizando una versión .NET <4.6, puede que tenga que cambiar parte del código para que funcione. ¡Disfrutar!

Una alternativa a la respuesta de Simon Mattes sería

Suponiendo que tienes:

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

Puede hacer esto si es para fines de prueba:

 var field = typeof(MyClass).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); field.SetValue(anIstanceOfMyClass, 3); 

depende de la propiedad si se trata de una propiedad calculada, no, a menos que sepa en qué se basa. si solo es un acceso a un campo privado, entonces puede intentar modificar el campo.

en general, sin embargo, es una muy mala idea, ya que es probable que no tenga conocimiento de los efectos secundarios que esto ocasionará.

 PropertyInfo isReadOnly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance| BindingFlags.NonPublic); //Remove the readonly property isReadOnly.SetValue(param, false, null); //.............put your code here..... // Set readonly property isReadOnly.SetValue(param, true, null);