2015-03-02 48 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