我想对一个只能通过反射访问的索引属性进行迭代,
但是(我完全知道这可能是一个令人尴尬的简单答案,MSDN / Google失败= /)除了PropertyInfo.GetValue(prop, counter)
之前递增一个计数器,我找不到/想到一种方法直到{ {1}}被抛出。
ALA:
TargetInvocationException
现在,这有一些问题...非常难看..解决方案..
如果它是多维的或者没有被整数索引,例如......
继承了我正在使用的测试代码,如果有人需要它,可以让它运行起来。如果有人有兴趣我正在制作一个自定义缓存系统而且.Equals不会削减它。
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 } ) );
}
}
}
答案 0 :(得分:8)
索引器的getter就像普通方法一样,除了它采用方括号而不是圆括号。您不希望能够自动确定方法的可接受值范围,因此对于索引器来说这是不可行的。
答案 1 :(得分: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)
方法。 Indexer是编译器的神奇之处。
class IndexedData
{
public double this[int index]
{
get { return (double)index; }
}
public double get_Item(int index)
{
return 1d;
}
}
答案 2 :(得分:3)
在索引属性中包含连续的索引号是没有什么可以打赌的 索引属性不是数组 反例:
Dictionary<int, bool> dictionary = new Dictionary<int, bool>();
dictionary[1] = true;
dictionary[5] = false;
根据类型,您通常有其他方法来获取可能的索引值,在本例中为dictionary.Keys
。如果可以使用您的类型,我会按此顺序尝试
IEnumerable<T>
。IEnumerable<T>
属性。如果你没有有效值的说明,也没有询问有效值是什么的方法,那么你几乎没有运气。
答案 3 :(得分:2)
您可以使用PropertyInfo.GetIndexParameters
查找索引属性参数的数量和类型。
我不认为你可以做些什么来找到这些参数的“合法”值,除非你“欺骗”并使用你可能拥有的内幕信息。
答案 4 :(得分:2)
管理进行改进,介意,还发现这个测试代码遭受自我引用的无限循环(例如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() );
}
}
答案 5 :(得分: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;
}
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;
}