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
How to Access Gmail API Using Service Account
Applying % Number Format to a Cell Value Using Openxml
How to Translate a List<String> into a SQLparameter for a SQL in Statement
Wpf Clickonce Dpi Awareness Per-Monitor V2
Mocking Static Methods Using Rhino.Mocks
A Way to Push Buffered Events in Even Intervals
How to Compare Two Images Using Byte Arrays
Using Graphics.Drawimage() to Draw Image with Transparency/Alpha Channel
How to Call a SQL Stored Procedure Using Entityframework 7 and ASP.NET 5
C#: How to Take a Screenshot of a Portion of Screen
Deserializing JSON Array into Strongly Typed .Net Object
Accuracy of Textrenderer.Measuretext Results
How to Get a Dimension (Slice) from a Multidimensional Array
How to Query for an Event Log Details with a Given Event Id
Very Simple Definition of Initializecomponent(); Method
The Type Initializer for 'Emgu.Cv.Cvinvoke' Threw an Exception