2011-11-11 9 views
5

प्राप्त करने के लिए रिकर्सिव रूटीन मैं एक पुनरावर्ती दिनचर्या बनाने का प्रयास कर रहा हूं जो किसी निर्दिष्ट ऑब्जेक्ट (.NET 3.5 में) के अंतर्गत सभी सदस्यों के लिए PropertyInfos पुनर्प्राप्त करेगा। तत्काल सदस्यों के लिए सब कुछ काम कर रहा है, लेकिन इसे नेस्टेड कक्षाओं के साथ-साथ (और उनके घोंसले वर्ग, आदि) को भी पार करने की जरूरत है।PropertyInfo

मुझे समझ में नहीं आता कि अनुभाग को कैसे नियंत्रित किया जाए जो नेस्टेड कक्षाओं को पार करती है। आप कोड के इस भाग को कैसे लिखेंगे?

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)); 
    } 

संपादित करें: मैं Harlam के सुझावों में से कुछ का उपयोग किया है, और एक काम कर समाधान के साथ आया था। यह घोंसला वाले वर्गों और सूचियों दोनों को संभालता है।

मैं निम्नलिखित

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); 
    } 
} 

साथ PropertyInfo के माध्यम से मेरे पिछले पाश से बदल दिया है मैं भी अगर कुछ एक सूची है देखने के लिए एक नई चेक जोड़ दिया है।

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

सहायता के लिए धन्यवाद!

उत्तर

5

मुझे लगता है कि यह आपके लिए काम करेगा। यहां विचार प्रत्येक कॉल से ProcessObject() पर एक गणना करने योग्य वस्तु को वापस करना है और फिर उन कॉल को कॉलर्स List<ObjectWalkerEntity> में रोल करना है।

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

उपज रिटर्न का उपयोग कर सकता है और बैक संदर्भ गुणों के लिए पहले से संसाधित वस्तुओं की एक सूची भी होनी चाहिए। – riezebosch

+0

यह लगभग काम करता है, लेकिन इसमें सूचियों के साथ समस्या आ रही है। – Rethic

0

Devscribe पर एक नज़र डालें। यह खुला स्रोत है और जेनरिक्स को संभालने सहित प्रत्येक प्रतिबिंब प्रकार को फिर से शुरू करने के लिए प्रतिबिंब का उपयोग करता है।

संबंधित मुद्दे