private static List <SettingsObject> BuildGraphImpl(object attributedObject, Stack <object> referenceStack) { List <SettingsObject> graph = new List <SettingsObject>(); // If arributed object is null return empty graph if (attributedObject == null) { return(graph); } // If a circular reference is detected then return empty graph if (referenceStack.Contains(attributedObject)) { return(graph); } // Push the current attributed part onto the reference stack referenceStack.Push(attributedObject); // Loop through properties on the attributed object foreach (var property in attributedObject.GetType().GetProperties()) { // Try get value from property object value = null; try { value = property.GetValue(attributedObject, null); } // ReSharper disable EmptyGeneralCatchClause catch (Exception) // ReSharper restore EmptyGeneralCatchClause { #if DEBUG //DIE execution DIE ... dude what are you doing?! Fix this otherwise the property won't show as an option in the settings treeview. #else // If there was a problem skip this property continue; #endif } // If value is null skip this property if (value == null) { continue; } // If a circular reference is detected then skip this property if (referenceStack.Contains(value)) { continue; } // Check if the property is adorned with the SettingsObjectAtribute object[] attributes = property.GetCustomAttributes(typeof(SettingsObjectAttribute), true); if (attributes.Length > 0) { SettingsObjectAttribute settingsObjectAttribute = attributes[0] as SettingsObjectAttribute; // Add settings object to graph if (settingsObjectAttribute != null) { graph.Add(new SettingsObject(value, settingsObjectAttribute.View, settingsObjectAttribute.ViewModel)); } } } // Find nested settings objects foreach (SettingsObject item in graph) { item.Children.AddRange(BuildGraphImpl(item.Object, referenceStack)); } // Pop from the reference stack referenceStack.Pop(); return(graph); }