키는 현재 속성 값인 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);
}
이는 천재입니다! 정말 고맙습니다. 위 화살표가 버튼 이었으면 좋겠다. 여러개의 "업"이 가능하고 끈적한 테이프로 엔터 키를 누르고있을 수있다. –
@Valamas, np, 우리는 리플렉션을 많이 사용합니다. 이것은 우리가 내부 공통 라이브러리에서 가지고있는 함수와 거의 같습니다. LINQ는 또한 리플렉션에서 실제로 잘 작동하지만 재귀 LINQ가 없기 때문에 여기서 도움이되지는 않습니다. –
자식 속성으로 포함 된 IList 개체가 있으면 코드가 작동하지 않습니다. –