如何迭代C#对象,查找特定类型的所有实例,以便构建这些实例的单独列表?

rem*_*mio 4 c# reflection enumeration properties

我需要有点类似于这个问题,除了它需要更深入地探索源对象.

这是一个代码示例:

public class Target {};

public class Analyzed
{
    public Target EasyOne { get; set; }
    public IList<Target> ABitMoreTricky { get; set; }
    public IList<Tuple<string, Target>> Nightmare { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

从一个实例中Analyzed,我想提取所有Target实例.

为了便于探索,我们可以假设以下内容:

  1. 仅浏览属性.
  2. 没有无限的参考循环.

现在,EasyOne是......很容易,但我正在寻找一些策略来让所有Target实例在更棘手的结构中丢失.

RQD*_*QDQ 12

这些方面的内容怎么样:

    public List<T> FindAllInstances<T>(object value) where T : class
    {

        HashSet<object> exploredObjects = new HashSet<object>();
        List<T> found = new List<T>();

        FindAllInstances(value, exploredObjects, found);

        return found;
    }

    private void FindAllInstances<T>(object value, HashSet<object> exploredObjects, List<T> found) where T : class
    {
        if (value == null)
            return;

        if (exploredObjects.Contains(value))
            return;

        exploredObjects.Add(value);

        IEnumerable enumerable = value as IEnumerable;

        if (enumerable != null)
        {
            foreach(object item in enumerable)
            {
                FindAllInstances<T>(item, exploredObjects, found);
            }
        }
        else
        {
            T possibleMatch = value as T;

            if (possibleMatch != null)
            {
                found.Add(possibleMatch);
            }

            Type type = value.GetType();

            PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty);

            foreach(PropertyInfo property in properties)
            {
                object propertyValue = property.GetValue(value, null);

                FindAllInstances<T>(propertyValue, exploredObjects, found);
            }

        }

    private void TestIt()
    {
        Analyzed analyzed = new Analyzed()
        {
            EasyOne = new Target(),
            ABitMoreTricky = new List<Target>() { new Target() },
            Nightmare = new List<Tuple<string, Target>>() { new Tuple<string, Target>("", new Target()) }
        };

        List<Target> found = FindAllInstances<Target>(analyzed);

        MessageBox.Show(found.Count.ToString());
    }
Run Code Online (Sandbox Code Playgroud)

  • 行`object propertyValue = property.GetValue(value,null);`如果你有一个索引属性(这[int index])会失败,很容易检查,但是你正在跳过东西.我重新编写它以使用FieldInfo,它就像属性一样简单. (2认同)