2011-11-11 11 views
5

almak için yinelenen yordam PropertyInfos belirli bir nesne (.NET 3.5) altında tüm üyeler için geri alacak bir yineleme yordamını oluşturmaya çalışıyorum. Acil üyeler için her şey çalışıyor, ama iç içe geçmiş sınıfları da (ve yuvalanmış sınıfları, vb.) Ayrıştırmak gerekiyor.PropertyInfo

İç içe geçmiş sınıfları ayrıştıran bölümün nasıl işleneceğini anlamıyorum. Kodun bu bölümünü nasıl yazdınız?

public class ObjectWalkerEntity 
{ 
    public object Value { get; set; } 
    public PropertyInfo PropertyInfo { get; set; } 
} 


public static class ObjectWalker 
{ 
    // This will be the returned object 
    static List<ObjectWalkerEntity> objectList = new List<ObjectWalkerEntity>(); 

    public static List<ObjectWalkerEntity> Walk(object o) 
    { 
     objectList.Clear(); 
     processObject(o); 
     return objectList; 
    } 

    private static void processObject(object o) 
    { 
     if (o == null) 
     { 
      return; 
     } 

     Type t = o.GetType(); 

     foreach (PropertyInfo pi in t.GetProperties()) 
     { 
      if (isGeneric(pi.PropertyType)) 
      { 
       // Add generic object 
       ObjectWalkerEntity obj = new ObjectWalkerEntity(); 
       obj.PropertyInfo = pi; 
       obj.Value = pi.GetValue(o, null); 
       objectList.Add(obj); 
      } 
      else 
      { 
       ////// TODO: Find a way to parse the members of the subclass... 
       // Parse each member of the non-generic object 
       foreach (Object item in pi.PropertyType) 
       { 
        processObject(item); 
       } 
      } 
     } 

     return; 
    } 

    private static bool isGeneric(Type type) 
    { 
     return 
      Extensions.IsSubclassOfRawGeneric(type, typeof(bool)) || 
      Extensions.IsSubclassOfRawGeneric(type, typeof(string)) || 
      Extensions.IsSubclassOfRawGeneric(type, typeof(int)) || 
      Extensions.IsSubclassOfRawGeneric(type, typeof(UInt16)) || 
      Extensions.IsSubclassOfRawGeneric(type, typeof(UInt32)) || 
      Extensions.IsSubclassOfRawGeneric(type, typeof(UInt64)) || 
      Extensions.IsSubclassOfRawGeneric(type, typeof(DateTime)); 
    } 

Düzenleme: Harlam'in önerilerden bazıları kullanılmış ve bir çalışma çözüm geldi ettik. Bu yuvalanmış sınıfları ve listeleri hem de işler.

ben de bir şey listesidir olup olmadığını görmek için yeni bir çek ekledik aşağıdaki

foreach (PropertyInfo pi in t.GetProperties()) 
{ 
    if (isGeneric(pi.PropertyType)) 
    { 
     // Add generic object 
     ObjectWalkerEntity obj = new ObjectWalkerEntity(); 
     obj.PropertyInfo = pi; 
     obj.Value = pi.GetValue(o, null); 
     objectList.Add(obj); 
    } 
    else if (isList(pi.PropertyType)) 
    { 
     // Parse the list 
     var list = (IList)pi.GetValue(o, null); 
     foreach (object item in list) 
     { 
      processObject(item); 
     } 
    } 
    else 
    { 
     // Parse each member of the non-generic object 
     object value = pi.GetValue(o, null); 
     processObject(value); 
    } 
} 

ile PropertyInfo aracılığıyla önceki döngü değiştirdik.

private static bool isList(Type type) 
{ 
    return 
     IsSubclassOfRawGeneric(type, typeof(List<>)); 
} 

Yardımın için teşekkürler!

cevap

5

Bunun sizin için çalışacağını düşünüyorum. Buradaki fikir, her çağrıda ProcessObject() numaralı numaraya bir numara döndürmek ve bu çağrıları List<ObjectWalkerEntity> numaralı arayanlara iletmektir.

public class ObjectWalkerEntity 
{ 
    public object Value { get; set; } 
    public PropertyInfo PropertyInfo { get; set; } 
} 

public static class ObjectWalker 
{ 
    public static List<ObjectWalkerEntity> Walk(object o) 
    { 
     return ProcessObject(o).ToList(); 
    } 

    private static IEnumerable<ObjectWalkerEntity> ProcessObject(object o) 
    { 
     if (o == null) 
     { 
     // nothing here, just return an empty enumerable object 
     return new ObjectWalkerEntity[0]; 
     } 

     // create the list to hold values found in this object 
     var objectList = new List<ObjectWalkerEntity>(); 

     Type t = o.GetType(); 
     foreach (PropertyInfo pi in t.GetProperties()) 
     { 
     if (IsGeneric(pi.PropertyType)) 
     { 
      // Add generic object 
      var obj = new ObjectWalkerEntity(); 
      obj.PropertyInfo = pi; 
      obj.Value = pi.GetValue(o, null); 
      objectList.Add(obj); 
     } 
     else 
     { 
      // not generic, get the property value and make the recursive call 
      object value = pi.GetValue(o, null); 
      // all values returned from the recursive call get 
      // rolled up into the list created in this call. 
      objectList.AddRange(ProcessObject(value)); 
     } 
     } 

     return objectList.AsReadOnly(); 
    } 

    private static bool IsGeneric(Type type) 
    { 
     return 
      IsSubclassOfRawGeneric(type, typeof(bool)) || 
      IsSubclassOfRawGeneric(type, typeof(string)) || 
      IsSubclassOfRawGeneric(type, typeof(int)) || 
      IsSubclassOfRawGeneric(type, typeof(UInt16)) || 
      IsSubclassOfRawGeneric(type, typeof(UInt32)) || 
      IsSubclassOfRawGeneric(type, typeof(UInt64)) || 
      IsSubclassOfRawGeneric(type, typeof(DateTime)); 
    } 

    private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) 
    { 
     while (toCheck != typeof(object)) 
     { 
     var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; 
     if (generic == cur) 
     { 
      return true; 
     } 
     toCheck = toCheck.BaseType; 
     } 
     return false; 
    } 
} 
+0

Verim dönüşünü kullanabilir ve ayrıca geri referans özellikleri için zaten işlenmiş nesnelerin bir listesini tutmalıdır. – riezebosch

+0

Bu neredeyse çalışıyor, ancak listelerde bir sorunla karşılaşıyor. – Rethic

0

Devscribe'a bakın. Açık kaynak kodludur ve her bir yansıma türünü yinelemek için Yansıma'yı kullanır.

İlgili konular