2010-11-24 85 views
8

我想itterate在索引屬性,我只能訪問通過反射,迭代(反射)

,但(我說這完全知道有可能是一個令人尷尬的答案很簡單, MSDN /谷歌失敗= /)除了PropertyInfo.GetValue(prop, counter)增加計數器之外,我找不到/想到一種方法,直到TargetInvocationException被拋出。

ALA:

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

現在,也有一些問題,這...非常難看.. ..解

,如果它是多維的或不被例如整數索引的.. 。

繼承人我使用的嘗試,並得到它的工作,如果有人需要它的測試代碼。如果任何人感興趣,我正在製作一個自定義緩存系統,而.Equals不會削減它。

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

什麼`對象海峽=新的String的目的(( 「你好,世界」)。ToArray的())`? – 2010-11-24 15:24:16

+0

只是一個示例變量傳遞給我的函數...正在嘗試定義一個字符串/字符串的不同方式,並將它留在一個尷尬的位...`object str =「Hello,World!」;``工作也一樣。 – 2010-11-24 15:35:10

+0

如果我有STRING鍵而不是整數,該怎麼辦?我不知道他們的名字。如何找到它們並使用? – Alexander 2017-12-07 20:51:47

回答

8

索引器的吸氣劑是就像正常的方法,不同的是它方括號中,不圓的。您不希望能夠自動確定某個方法的可接受值的範圍,因此對於索引器來說這是不可行的。

+0

解決方法是使用反射來查找名爲`Length`或`Count`的成員屬性,並將其用作整數索引屬性的上限,或者將字符串索引屬性稱爲`Keys`的屬性。 – Dai 2012-09-05 01:18:58

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>屬性每個索引屬性幾個索引屬性。

如果您沒有指定有效值並且沒有詢問有效值的方法,那麼您幾乎不走運。

4

索引器將被編譯爲方法。這裏有一個例子:

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

它會被編譯成這樣的:

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

下面的代碼,因爲有在類中的兩個double get_Item(int)方法不能被編譯。索引器是編譯器的神奇之處。

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

    public double get_Item(int index) 
    { 
     return 1d; 
    } 
} 
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; 
}