简体   繁体   English

在C#中获取对类型中所有类型对象的引用

[英]Getting a reference to all objects of a type in class in C#

Say I have a class with reference variables to some objects of type Foo. 假设我有一个带有对Foo类型的某些对象的引用变量的类。 Say I now want to get a list of all of these variables dynamically, meaning if I add a new one that one will also be in the list. 假设我现在要动态获取所有这些变量的列表,这意味着如果我添加一个新变量,则该变量也将出现在列表中。

I have tried using reflection, but I am not very experienced with it, so I think that is the right way but I'm not completely sure. 我已经尝试过使用反射,但是我对反射不是很有经验,所以我认为这是正确的方法,但是我不确定。

public class Foo() {
    public void Setup() {
        // Runs some code
    }
}

public class MyClass() {
    public Foo a;
    public Foo b;
    public Foo c;
    public Foo d;
    public Foo e;

    // Current constructor, does what I want but in a non-elegant way
    MyClass() {

        Foo[] foos= new Foo[] {
            a,
            b,
            c,
            d,
            e
        };
        foreach(Foo foo in foos) {
            foo.Setup();
        }
    }

    // The constructor I want, with GetAllMembersOfType<T>() dynamically
    // returning new objects as I add them to the class later
    MyClass() {

        Foo[] foos = GetAllMembersOfType<Foo>();
        foreach(Foo foo in foos) {
            foo.Setup();
        }
    }
}

How could I create a method like GetAllMembersOfType<T>() ? 如何创建类似GetAllMembersOfType<T>() Or at least a way to call Setup() on all member variables of type Foo ? 或者至少是一种对Foo类型的所有成员变量调用Setup()的方法?

Using reflection to get all private and public fields of a type, your constructor will become this: 使用反射获取类型的所有privatepublic字段,您的构造函数将变为:

public class MyClass() 
{
    public Foo a;
    public Foo b;
    public Foo c;
    public Foo d;
    public Foo e;

    MyClass() 
    {
        Foo[] foos = GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
            .Where(fieldInfo => fieldInfo.FieldType.Equals(typeof(Foo)))
            .Select(fieldInfo => fieldInfo.GetValue(this))
            .Cast<Foo>()
            .ToArray();

        foreach(Foo foo in foos) 
        {
            foo.Setup();
        }
    }
}

But this fields might not be initialized. 但是此字段可能未初始化。 Maybe it's more convenient to call Setup() on instantiation either as an external call or constructor call. 也许在实例化时以外部调用或构造函数调用方式调用Setup()更为方便。

@BionicCode answer works perfectly, but you can also invoke the method with reflection if you want. @BionicCode答案可以完美地工作,但是您也可以根据需要调用反射方法。 It would look something like this: 它看起来像这样:

public MyClass()
{
  MethodInfo method = typeof(Foo).GetMethod("Setup", BindingFlags.Instance |
    BindingFlags.NonPublic | BindingFlags.Public);

  foreach (FieldInfo f in GetType().GetFields(BindingFlags.Instance |
    BindingFlags.NonPublic | BindingFlags.Public)
    .Where(fieldInfo => fieldInfo.FieldType.Equals(typeof(Foo))))
  {
    method.Invoke(f.GetValue(this), null);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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