Recursivamente obter propriedades e propriedades filho de um object

Ok, a princípio, achei que isso era fácil, e talvez seja, e estou cansado demais – mas aqui está o que estou tentando fazer. Digamos que eu tenha os seguintes objects:

public class Container { public string Name { get; set; } public List
Addresses { get; set; } } public class Address { public string AddressLine1 { get; set; } public string AddressLine2 { get; set; } public List Telephones { get; set; } } public class Telephone { public string CellPhone { get; set; } }

O que eu preciso ser capaz de fazer, é ‘achatar’ os nomes da propriedade Containers em uma string (incluindo TODAS as propriedades filho e propriedades filho das propriedades filho) que seriam algo como isto:

 Container.Name, Container.Addresses.AddressLine1, Container.Addresses.AddressLine2, Container.Addresses.Telephones.CellPhone 

Isso faz algum sentido? Eu não consigo envolvê-lo na minha cabeça.

Eu sugiro que você marque todas as classs, você precisa pegar, com atributo personalizado depois que você poderia fazer algo parecido com isto

  class Program { static void Main(string[] args) { var lines = ExtractHelper.IterateProps(typeof(Container)).ToArray(); foreach (var line in lines) Console.WriteLine(line); Console.ReadLine(); } } static class ExtractHelper { public static IEnumerable IterateProps(Type baseType) { return IteratePropsInner(baseType, baseType.Name); } private static IEnumerable IteratePropsInner(Type baseType, string baseName) { var props = baseType.GetProperties(); foreach (var property in props) { var name = property.Name; var type = ListArgumentOrSelf(property.PropertyType); if (IsMarked(type)) foreach (var info in IteratePropsInner(type, name)) yield return string.Format("{0}.{1}", baseName, info); else yield return string.Format("{0}.{1}", baseName, property.Name); } } static bool IsMarked(Type type) { return type.GetCustomAttributes(typeof(ExtractNameAttribute), true).Any(); } public static Type ListArgumentOrSelf(Type type) { if (!type.IsGenericType) return type; if (type.GetGenericTypeDefinition() != typeof(List<>)) throw new Exception("Only List are allowed"); return type.GetGenericArguments()[0]; } } [ExtractName] public class Container { public string Name { get; set; } public List
Addresses { get; set; } } [ExtractName] public class Address { public string AddressLine1 { get; set; } public string AddressLine2 { get; set; } public List Telephones { get; set; } } [ExtractName] public class Telephone { public string CellPhone { get; set; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = true)] public sealed class ExtractNameAttribute : Attribute { }

De acordo com meu comentário, você poderia usar algo assim se sempre for um tipo de lista genérico que você deseja vincular a um tipo filho. IteratePropertiesRecursively é um iterador sobre as propriedades do tipo determinado, que enumerará recursivamente as propriedades do tipo e todos os tipos filho vinculados por meio de uma Lista genérica.

 protected void Test() { Type t = typeof(Container); string propertyList = string.Join(",", IteratePropertiesRecursively("", t).ToArray()); // do something with propertyList } protected IEnumerable IteratePropertiesRecursively(string prefix, Type t) { if (!string.IsNullOrEmpty(prefix) && !prefix.EndsWith(".")) prefix += "."; prefix += t.Name + "."; // enumerate the properties of the type foreach (PropertyInfo p in t.GetProperties()) { Type pt = p.PropertyType; // if property is a generic list if (pt.Name == "List`1") { Type genericType = pt.GetGenericArguments()[0]; // then enumerate the generic subtype foreach (string propertyName in IteratePropertiesRecursively(prefix, genericType)) { yield return propertyName; } } else { // otherwise enumerate the property prepended with the prefix yield return prefix + p.Name; } } } 

Nota: Esse código não manipulará corretamente um tipo que se inclui recursivamente como um tipo de uma de suas propriedades. Tentar iterar esse tipo resultará em um StackOverflowException , como apontado por @Dementic (obrigado!).