I'm trying to call a method for each of the variables/instances of a given type in my class. I've found other posts describing a way to do this using reflection. However, the examples I have found are using Activator.CreateInstance()
or with only one instance of the given class (using FieldInfo.GetValue()
). I would like to call this method on the instances themselves, rather than creating a new instance and calling the method. Is this possible?
Example of what I'm trying to do:
public class Data
{
int x;
public Data(int x){
this.x = x;
}
public void Print()
{
Console.WriteLine(x);
}
}
public class MyClass
{
private Data instance1 = new Data(5);
private Data instance2 = new Data(4);
...
public void PrintAllX(){
var fields = GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(f => f.FieldType == typeof(Data));
foreach(FieldInfo field in fields)
{
MethodInfo method = field.FieldType.GetMethod("Print");
var instance = ?;// need to get 'Data' instance for each field here (instance1, instance2)
method?.Invoke(instance, null);
}
}
}
I've tried setting instance equal to field.GetValue(null)
for this as suggested in this post, but it did not work giving me the error: TargetException: Non-static field requires a target
.
CodePudding user response:
Thanks to madreflection's suggestion I was able to come up with a solution for my problem. Here's the solution to the example code from my question. Note that as mentioned in his comment, using a collection may be better for subsequent calls. However, in my case I am only ever calling this method once so the performance of subsequent calls isn't a problem.
public void PrintAllX()
{
List<object> fieldObjs = GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Select(s => s.GetValue(this)).ToList();
foreach (object obj in fieldObjs)
{
if (obj == null) continue;
if (obj.GetType() == typeof(Data))
((Data)obj).Print();
}
}
CodePudding user response:
Perhaps I am missing something.. but reflection may not be the right tool here.
Instead of making each of your Data
fields separate variables, what if you put them in a collection.. then you can avoid reflection entirely.
Something like:
public class MyClass {
private List<Data> datas = new List<Data> {
new Data(5),
new Data(4) // etc...
};
public void PrintAllX() {
foreach(Data data in datas) {
data.Print();
}
}
}