反射:以递归方式搜索字符串值的对象,然后报告路径

时间:2011-03-30 01:12:48

标签: c# reflection recursion

我正在尝试在复杂对象中查找值。有没有人知道是否有一个助手类已经这样做了?

希望能够搜索一个对象,同时观察无限循环保护,找到包含“foo”的tostring值,然后返回找到foo的属性路径。或者找到一个路径foo数组。

所以如果有人在我自己承担这个代码之前有现有的代码;我将非常感激。

1 个答案:

答案 0 :(得分:1)

关键是你想要在递归搜索你所追求的值以及Stack个被访问对象时跳过当前属性的HashSet并跳过它们。您还需要小心处理异常处理,因此中间的异常不会弄乱堆栈。

    public static string[] FindPathToProperty(object item, string propertyValueToFind)
    {
        var pathToProperty = new Stack<string>();
        var visitedObjects = new HashSet<object> {item};

        FindPathToProperty(item, propertyValueToFind, pathToProperty, visitedObjects);

        var finalPath = pathToProperty.ToArray();
        Array.Reverse(finalPath);
        return finalPath;
    }

    private static bool FindPathToProperty(object item, string propertyValueToFind, Stack<string> pathToProperty, HashSet<object> visitedObjects)
    {
        foreach (var property in item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            try
            {
                var value = property.GetValue(item, null);

                if (visitedObjects.Contains(value))
                {
                    continue;                       
                }

                visitedObjects.Add(value);

                pathToProperty.Push(property.Name);

                bool found = false;
                try
                {
                    found = propertyValueToFind.Equals(value) ||
                            FindPathToProperty(value, propertyValueToFind, pathToProperty, visitedObjects);
                }
                finally
                {
                    if (!found)
                    {
                        pathToProperty.Pop();
                    }
                }
                if (found)
                {
                    return true;
                }
            }
            catch
            {
                continue;
            }
        }

        return false;
    }

    public static void Test()
    {
        Test(new { X = "find" }, "X");
        Test(new { X = "no", Y = "find" }, "Y");
        Test(new { A = new { X = "no", Y = "find" } }, "A.Y");
    }

    private static void Test(object item, string expected)
    {
        string actual = string.Join(".", FindPathToProperty(item, "find"));
        Console.WriteLine("{0} : {1}\r\n      {2}",
                          actual == expected ? "ok " : "BAD",
                          expected,
                          actual);
    }