2010-11-24 20 views
8

मैं एक अनुक्रमित संपत्ति है कि मैं केवल प्रतिबिंब के माध्यम से करने के लिए उपयोग किया है से अधिक itterate करना चाहते हैं,पुनरावृत्ति (प्रतिबिंब)

लेकिन (और मैं वहाँ शायद एक शर्मनाक सरल जवाब है कि पूरी जानकारी में यह कहते हैं, एमएसडीएन/Google असफल = /) TargetInvocationException फेंकने तक PropertyInfo.GetValue(prop, counter) पर काउंटर बढ़ाने के अलावा मैं किसी तरीके से नहीं ढूंढ सकता/सोच सकता हूं।

आला:

foreach (PropertyInfo prop in obj.GetType().GetProperties()) 
{ 
    if (prop.GetIndexParameters().Length > 0) 
    { 
     // get an integer count value, by incrementing a counter until the exception is thrown 
     int count = 0; 
     while (true) 
     { 
      try 
      { 
       prop.GetValue(obj, new object[] { count }); 
       count++; 
      } 
      catch (TargetInvocationException) { break; } 
     } 

     for (int i = 0; i < count; i++) 
     { 
      // process the items value 
      process(prop.GetValue(obj, new object[] { i })); 
     } 
    } 
} 

अब, कुछ मुद्दों पर .. इस ... बहुत बदसूरत .. समाधान के साथ देखते हैं

क्या हुआ अगर यह बहु-आयामी या उदाहरण के लिए पूर्णांक द्वारा अनुक्रमित नहीं है .. ।

यहाँ परीक्षण कोड मैं कोशिश करते हैं और अगर कोई यह की जरूरत है काम कर इसे पाने के लिए उपयोग कर रहा हूँ। यदि कोई दिलचस्पी लेता है तो मैं एक कस्टम कैशिंग सिस्टम बना रहा हूं और .क्वल्स इसे काट नहीं देता है।

static void Main() 
    { 
     object str = new String(("Hello, World").ToArray()); 

     process(str); 

     Console.ReadKey(); 
    } 

    static void process(object obj) 
    { 
     Type type = obj.GetType(); 

     PropertyInfo[] properties = type.GetProperties(); 

     // if this obj has sub properties, apply this process to those rather than this. 
     if (properties.Length > 0) 
     { 
      foreach (PropertyInfo prop in properties) 
      { 
       // if it's an indexed type, run for each 
       if (prop.GetIndexParameters().Length > 0) 
       { 
        // get an integer count value 
        // issues, what if it's not an integer index (Dictionary?), what if it's multi-dimensional? 
        // just need to be able to iterate through each value in the indexed property 
        int count = 0; 
        while (true) 
        { 
         try 
         { 
          prop.GetValue(obj, new object[] { count }); 
          count++; 
         } 
         catch (TargetInvocationException) { break; } 
        } 

        for (int i = 0; i < count; i++) 
        { 
         process(prop.GetValue(obj, new object[] { i })); 
        } 
       } 
       else 
       { 
        // is normal type so. 
        process(prop.GetValue(obj, null)); 
       } 
      } 
     } 
     else 
     { 
      // process to be applied to each property 
      Console.WriteLine("Property Value: {0}", obj.ToString()); 
     } 
    } 
+0

क्या 'वस्तु str = नया स्ट्रिंग का उद्देश्य है ((" हैलो, दुनिया ") toArray()।)' है? –

+0

बस मेरे फ़ंक्शन को पास करने के लिए एक उदाहरण चर ... स्ट्रिंग/स्ट्रिंग को परिभाषित करने के विभिन्न तरीकों का प्रयास कर रहा था और इसे थोड़ा अजीब पर छोड़ दिया ... 'object str =" हैलो, वर्ल्ड! ";' बस काम करता है। –

+0

यदि मेरे पास STRING कुंजी हैं, तो पूर्णांक नहीं है? मैं उनके नाम नहीं जानता। उन्हें कैसे ढूंढें और उपयोग करें? – Alexander

उत्तर

8

एक इंडेक्सर के गेटर, बस सामान्य विधि की तरह है। आप किसी विधि के लिए स्वीकार्य मानों की सीमा को स्वचालित रूप से निर्धारित करने में सक्षम होने की उम्मीद नहीं करेंगे, इसलिए यह सूचकांक के लिए व्यवहार्य नहीं है।

+0

एक वर्कअराउंड 'लम्बाई' या 'गणना' नामक सदस्य संपत्ति को खोजने के लिए प्रतिबिंब का उपयोग करना है और पूर्णांक-अनुक्रमित गुणों के लिए ऊपरी भाग के रूप में या स्ट्रिंग-अनुक्रमित संपत्ति के लिए 'कुंजी' नामक एक संपत्ति का उपयोग करना है। – Dai

2

आप PropertyInfo.GetIndexParameters का उपयोग संख्या और अनुक्रमित संपत्ति मापदंडों के प्रकार पता लगाने के लिए कर सकते हैं।

मुझे नहीं लगता कि कुछ भी आप की खोज क्या इन मानकों के लिए "कानूनी" मान होते हैं, जब तक आप "धोखा" और जानकारी के अंदर का उपयोग तुम क्या है कि संपत्ति है पर हो सकता है के बारे में कुछ नहीं कर सकता है। सिवाय यह वर्ग कोष्ठक, नहीं दौर लोगों लेता

3

एक अनुक्रमित संपत्ति में होने अनुक्रमिक सूचकांक आप पर दांव लगा सकते कुछ भी नहीं है।
इंडेक्स किए गए गुण सरणी नहीं हैं।
काउंटर उदाहरण:

Dictionary<int, bool> dictionary = new Dictionary<int, bool>(); 
dictionary[1] = true; 
dictionary[5] = false; 

प्रकार आप आमतौर पर अन्य तरीकों इस मामले dictionary.Keys में, संभव सूचकांक मूल्यों को प्राप्त करने के लिए है पर निर्भर करता है। यदि यह आपके प्रकार के साथ संभव है तो मैं इस क्रम में

  1. प्रकार के लिए IEnumerable<T> लागू करें।
  2. आप कई अनुक्रमित गुण आप प्रत्येक अनुक्रमित संपत्ति के लिए एक इसी IEnumerable<T> संपत्ति को लागू कर सकते हैं।

यदि आपके पास मान्य मानों का कोई विनिर्देश नहीं है और वैध मान क्या हैं, यह पूछने की कोई विधि नहीं है, तो आप भाग्य से काफी अधिक हैं।

+0

दुर्भाग्यवश मैं रनटाइम तक इनपुट प्रकार की नीची हूं (इसे वास्तव में ऑब्जेक्ट एक्सटेंशन विधि के रूप में कार्यान्वित किया गया है) लेकिन आपने मुझे एक आईनेमरेबल कार्यान्वयन की खोज करने का विचार दिया। अनुक्रमित मानों के माध्यम से पुन: प्रयास करने के लिए धन्यवाद –

4

सूचकांक विधियों के लिए संकलित किए जाएंगे।

class IndexedData 
{ 
    public double this[int index] 
    { 
     get { return (double)index; } 
    } 
} 

वह कुछ इस तरह करने के लिए संकलित किया जाएगा: क्योंकि वहाँ कक्षा में दो double get_Item(int) तरीके हैं

public double get_Item(int index) 
{ 
    return (double)index; 
} 

निम्नलिखित कोड संकलित नहीं किया जा सकता यहाँ एक उदाहरण है। इंडेक्सर कंपाइलर का जादू है।

class IndexedData 
{ 
    public double this[int index] 
    { 
     get { return (double)index; } 
    } 

    public double get_Item(int index) 
    { 
     return 1d; 
    } 
} 
+0

। स्ट्रिंग पहले से ही चार प्रकार का अनुक्रमित पैरामीटर है ... इसलिए मैं करना चाहता था: 'foreach (str में char c) Console.write (c); ', केवल प्रतिबिंब के साथ .. –

+0

@ Dead.Rabit: देखें मेरा सम्पादन। मुझे लगता है कि यह आपको सूचकांक को समझने में मदद करेगा। –

1

एक सुधार, मन बनाने के लिए प्रबंधित, यह भी पता चला कि इस परीक्षण कोड आत्म संदर्भ के लिए अनंत लूप (उदाहरण के लिए Array.Syncroot)

से ग्रस्त संक्षेप यह अब चीजें हैं जो से विरासत पाए जाने पर IEnumerable (जो सबसे अनुक्रमणित है बातें) और उन पर एक foreach पाश का उपयोग करें और ज्ञान है कि मौजूदा (बदसूरत) कोड स्ट्रिंग्स के लिए काम करता है, यह अब अधिक गहन आवंटित है तो यह हुआ करता था के साथ मिलकर ...

खुशी है लेकिन निराश है कि एक अच्छा जवाब प्रतीत नहीं होता है।

हर किसी को मदद के लिए धन्यवाद


अपडेट किया गया परीक्षण कोड किसी को एक समान स्थिति

static void process(object obj) 
    { 
     Type type = obj.GetType(); 

     PropertyInfo[] properties = type.GetProperties(); 

     // if this obj has sub properties, apply this process to those rather than this. 
     if (properties.Length > 0) 
     { 
      foreach (PropertyInfo prop in obj.GetType().GetProperties()) 
      { 
        if (prop.PropertyType.FindInterfaces((t, c) => t == typeof(IEnumerable), null).Length > 0) 
        { 
         MethodInfo accessor = prop.GetGetMethod(); 
         MethodInfo[] accessors = prop.GetAccessors(); 

         foreach (object item in (IEnumerable)obj) 
         { 
          process(item); 
         } 
        } 
        else if (prop.GetIndexParameters().Length > 0) 
        { 
         // get an integer count value, by incrementing a counter until the exception is thrown 
         int count = 0; 
         while (true) 
        { 
         try 
         { 
          prop.GetValue(obj, new object[] { count }); 
          count++; 
         } 
         catch (TargetInvocationException) { break; } 
        } 

        for (int i = 0; i < count; i++) 
        { 
         // process the items value 
         process(prop.GetValue(obj, new object[] { i })); 
        } 
       } 
       else 
       { 
        // is normal type so. 
        process(prop.GetValue(obj, null)); 
       } 
      } 
     } 
     else 
     { 
      // process to be applied to each property 
      Console.WriteLine("Property Value: {0}", obj.ToString()); 
     } 
    } 
0

ऊपर कोड और इस प्रश्न से संबंधित लोगों में खुद को पाता है समस्या के लिए वास्तव में मददगार थे कि मैं सामना कर रहा था। मैं अपना कोड पोस्ट कर रहा हूं और मुझे उम्मीद है कि यह आपके लिए भी काम करेगा।

public ActionResult Survey(SurveyCollection surveyCollection) { if (surveyCollection != null) { Answer_DropDownCordinateOptionList traceObject = new Answer_DropDownCordinateOptionList(); IList traceObjectCollection = new List(); traceObjectCollection = ExtractNestedObjects(surveyCollection, traceObject, traceObjectCollection); }

return View(surveyCollection); 
} 

private static IList<T> ExtractNestedObjects<T>(object baseObject, T findObject, IList<T> resultCollection) 
{ 
    if (baseObject != null && findObject != null) 
    { 
     Type typeDestination = findObject.GetType(); 

     Type typeSource = baseObject.GetType(); 
     PropertyInfo[] propertyInfoCollection = typeSource.GetProperties(); 
     foreach (PropertyInfo propertyInfo in propertyInfoCollection) 
     { 
      if (propertyInfo.PropertyType.FindInterfaces((t, c) => t == typeof(IEnumerable), null).Length > 0) 
      { 
       if(propertyInfo.GetValue(baseObject, null) != null) 
       { 
        if(propertyInfo.GetValue(baseObject, null).GetType().IsPrimitive) 
        { 
         ExtractNestedObjects<T>(propertyInfo.GetValue(baseObject, null), findObject, resultCollection); 
        } 
        else if (propertyInfo.GetValue(baseObject, null).GetType().IsGenericType) 
        { 
         foreach (var item in (IList)propertyInfo.GetValue(baseObject, null)) 
         { 
          ExtractNestedObjects<T>(item, findObject, resultCollection); 
         } 
        } 
       } 
      } 
      else 
      { 
       if (propertyInfo.Name == typeDestination.Name) 
       { 
        if (propertyInfo.GetValue(baseObject, null) != null) 
        { 
         resultCollection.Add((T)propertyInfo.GetValue(baseObject, null)); 
        } 
       } 

       ExtractNestedObjects<T>(propertyInfo.GetValue(baseObject, null), findObject, resultCollection); 
      } 
     } 
    } 
    return resultCollection; 
}