Отражение: поиск объекта по строковому значению, рекурсивно, а затем пути сообщения - PullRequest
1 голос
/ 30 марта 2011

Я пытаюсь найти значение в сложном объекте.Кто-нибудь знает, существует ли какой-нибудь вспомогательный класс, который уже делает это?

Хотел бы иметь возможность искать объект, одновременно наблюдая за защитой бесконечного цикла, чтобы найти значение tostring, содержащее "foo", а затемвернуть путь свойства, в котором был найден foo. Или массив путей, в котором был найден foo.

Так что, если кто-то имеет удобный существующий код, прежде чем я сам предприму это;Я был бы очень признателен.

1 Ответ

1 голос
/ 30 марта 2011

Ключ в том, что вы хотите сохранить 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);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...