2010-11-24 101 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; 
}