2015-03-02 53 views
2

我想遞歸構建一個複雜的對象。遞歸創建自定義複合對象

public class Name 
{ 
    public string firstName {get;set;} 
    public string lastName {get;set;} 
} 

public class Address 
{ 
    public string city {get;set;} 
    public string state {get;set;} 
    public string street {get;set;} 
    public string zip {get;set;} 
} 

public class Customer 
{ 
    public Name customerName {get;set;} 
    public Address customerAddress {get;set;} 
    public Guid id {get;set;} 
} 

讓我們說,客戶生活在一個大會,我加載在飛行:) 我想實例化一個Customer類型的,填充它的屬性。 Customer對象具有更多自定義對象和Guid屬性。我如何使用遞歸來創建Customer對象及其嵌套對象。我在下面有一些代碼,我偶然發現我應該使用遞歸。

static object TraversePropertyInfo(object obj, Assembly assembly) 
    { 
     Console.WriteLine(obj.GetType().Name); 

     foreach(PropertyInfo pi in obj.GetType().GetProperties()) 
     { 
      if(pi.PropertyType.IsClass && pi.PropertyType.Namespace != "System") 
      { 
       if(pi.PropertyType.UnderlyingSystemType.GenericTypeArguments.Count() > 0) 
       { 
        Console.WriteLine("\tIList<{0}>", pi.Name); 
       } 
       else 
       { 
        Console.WriteLine("\t{0}\t<class>", pi.Name); 
        object child = Activator.CreateInstance(assembly.GetType(pi.PropertyType.FullName)); // create the child instance 
        obj.GetType().GetProperty(pi.Name).SetValue(obj, child);        // set the child on the parent 
        // but the child can have children... 
        // I should be using recurrsion here 
       } 
      } 
      else 
      { 
       Console.WriteLine("\t{0}\t{1}", pi.Name, pi.PropertyType); 
      } 
     } 
     return obj; 
    } 
+0

是否有任何的類都有一個構造函數,需要在參數? – dustinmoris 2015-03-02 16:51:36

+0

沒有任何類都沒有構造函數,在foreach循環中返回的參數 – Mateo 2015-03-02 16:54:42

回答

5
void Main() 
{ 
    Create<Customer>().Dump(); 
} 

// Define other methods and classes here 

public class Name 
{ 
    public string Firstname { get; set; } 
    public string Lastname { get; set; } 
} 

public class Address 
{ 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Street { get; set; } 
    public string Zip { get; set; } 
} 

public class Customer 
{ 
    public Name CustomerName { get; set; } 
    public Address CustomerAddress { get; set; } 
    public Guid Id { get; set; } 
} 

public static T Create<T>() 
{ 
    var type = typeof(T); 

    return (T)Create(type); 
} 

public static object Create(Type type) 
{ 
    var obj = Activator.CreateInstance(type); 

    foreach(var property in type.GetProperties()) 
    { 
     var propertyType = property.PropertyType; 

     if (propertyType.IsClass 
      && string.IsNullOrEmpty(propertyType.Namespace) 
      || (!propertyType.Namespace.Equals("System") 
       && !propertyType.Namespace.StartsWith("System."))) 
     { 
      var child = Create(propertyType); 

      property.SetValue(obj, child); 
     } 
    } 

    return obj; 
} 
+0

非常好,謝謝! – Mateo 2015-03-02 18:34:16

+0

這太棒了。 – AnotherDeveloper 2016-11-18 23:51:49

0

也許這將工作:

static object TraversePropertyInfo(object obj, Assembly assembly) 
{ 
    Console.WriteLine(obj.GetType().Name); 
    // we stop the iteration when we reached the root-class "object" 
    // which won´t add any custom properties 
    if (obj.GetType() == typeof(object) return obj; 


    foreach(PropertyInfo pi in obj.GetType().GetProperties()) 
    { 
     if(pi.PropertyType.IsClass && pi.PropertyType.Namespace != "System") 
     { 
      if(pi.PropertyType.UnderlyingSystemType.GenericTypeArguments.Count() > 0) 
      { 
       Console.WriteLine("\tIList<{0}>", pi.Name); 
      } 
      else 
      { 
       Console.WriteLine("\t{0}\t<class>", pi.Name); 
       object child = Activator.CreateInstance(assembly.GetType(pi.PropertyType.FullName)); // create the child instance 
       child = TraversePropertyInfo(child, child.GetType().Assembly); 
       obj.GetType().GetProperty(pi.Name).SetValue(obj, child);        // set the child on the parent 
       // this will do the recursion 
       return obj; 
      } 
     } 
     else 
     { 
      Console.WriteLine("\t{0}\t{1}", pi.Name, pi.PropertyType); 
     } 
    } 
    return obj; 
} 
+0

將覆蓋原始對象並在遍歷所有對象之前返回。 :( – Mateo 2015-03-02 16:53:54

+0

@Mateo現在應該可以工作 – HimBromBeere 2015-03-02 16:58:36

+0

不錯!釘上它 – Mateo 2015-03-02 18:25:49