I have a struct that has a ton of named bool members. (Please leave good practices and such out of consideration now for the sake of the example).
I want to randomly set these values to either true or false, just for testing purposes.
How can I do this through reflection?
This is what I have so far:
Random r = new Random();
foreach (var bool_field in state.GetType().GetFields().Where(x => x.GetType() == false.GetType()))
{
bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false);
}
Unfortunately, it never enters the loop.
UPDATE 1:
Here is how the SystemState struct looks like, which is the type of the state variable. It is filled with bool auto properties.
public struct SystemState
{
...
public bool CanYouHelpMeOnThisOne { get; set; }
...
}
UPDATE 2:
The solution posted below seems nice, but it does not work. The reason is that SystemState is a struct not a class. Therefor it is a Value type not a Reference type, so calling the SetValue method has no effect. After changing SystemState to class, the below solution works perfectly.
Now is there any other way, to achieve this without changing SystemState to class?
To set property values via Reflection, you must use the Type. GetProperty() method, then invoke the PropertyInfo. SetValue() method. The default overload that we used accepts the object in which to set the property value, the value itself, and an object array, which in our example is null.
We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.
SetValue(Object, Object, Object[]) Sets the property value of a specified object with optional index values for index properties.
Reflection provides objects (of type Type) that describe assemblies, modules, and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties.
At first you need to change the Where
clause:
x => x.FieldType == false.GetType()
As the type of x
is FieldInfo
Since the last OP's edit it's not fields there, but properties. So, you should use GetProperties
to get the list of properties, and compare the PropertyType
, as x
would be PropertyInfo
then. Also the SetValue
method is gonna to have the other signature.
foreach (var bool_field in state.GetType()
.GetProperties()
.Where(x => x.PropertyType == false.GetType()))
{
bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false, null);
}
Based on OP's comments, if you do want to access the backing fields, you can use the following code:
var fs = state.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.Where(x => x.FieldType == typeof(bool));
foreach (var f in fs)
{
f.SetValue(state, true);
}
The overload of GetFields
without arguments returns all the public fields of the current Type. While in your case you need the private
ones, so use the Type.GetFields Method (BindingFlags) with the suitable BindingFlags
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With