简体   繁体   中英

Get Object Instances from FieldInfo

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 .

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

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 Data instance1 = new Data(5);
    private Data instance2 = new Data(4);

    private List<Data> datas = new List<Data> {
        instance1,
        instance2    // etc...
    };

    public void PrintAllX() {
        foreach(Data data in datas) {
            data.Print();
        }
    }
}

Update: modified code to be a hybrid - field variables, with a List of those field variables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM