How about something in this direction:
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()); }
source share