[英]iterating through an indexed property (Reflection)
我想对我只能通过反射访问的索引属性进行迭代,
但是(并且我完全知道这可能是一个令人尴尬的简单答案,MSDN / Google失败= /)除了在PropertyInfo.GetValue(prop, counter)
递增计数器之外我找不到/想到一种方法直到TargetInvocationException
被扔了。
翼:
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() );
}
}
索引器的getter就像普通方法一样,除了它采用方括号而不是圆括号。 您不希望能够自动确定方法的可接受值的范围,因此对于索引器来说这是不可行的。
索引器将编译为方法。 这是一个例子:
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;
}
}
在索引属性中具有顺序索引号是没有什么可以打赌的。
索引属性不是数组。
反例:
Dictionary<int, bool> dictionary = new Dictionary<int, bool>();
dictionary[1] = true;
dictionary[5] = false;
根据类型,您通常有其他方法来获取可能的索引值,在本例中为dictionary.Keys
。 如果你的类型可以,我会尝试这个顺序
IEnumerable<T>
。 IEnumerable<T>
属性。 如果你没有有效值的规范,也没有询问有效值是什么的方法,那么你几乎没有运气。
您可以使用PropertyInfo.GetIndexParameters
来查找索引属性参数的数量和类型。
我不认为你可以做些什么来找到这些参数的“合法”值,除非你“欺骗”并使用你可能拥有的内部信息。
管理进行改进,介意,还发现这个测试代码遭受自我引用的无限循环(例如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() );
}
}
以上代码和这个问题的相关内容对我所面临的问题非常有帮助。 我发布了我的代码,我希望这个代码也适用于你们。
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; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.