C# 迭代索引属性(反射)

C# 迭代索引属性(反射),c#,.net,reflection,C#,.net,Reflection,我想对一个只有通过反射才能访问的索引属性进行排序 但是(我这么说是因为我完全知道可能有一个令人尴尬的简单答案,MSDN/Google fail=/)在抛出TargetInvocationException之前,除了在PropertyInfo.GetValue(prop,counter)上增加计数器外,我找不到/想不出其他方法 阿拉: foreach(obj.GetType().GetProperties()中的PropertyInfo属性) { if(prop.GetIndexParameter

我想对一个只有通过反射才能访问的索引属性进行排序

但是(我这么说是因为我完全知道可能有一个令人尴尬的简单答案,MSDN/Google fail=/)在抛出
TargetInvocationException
之前,除了在
PropertyInfo.GetValue(prop,counter)
上增加计数器外,我找不到/想不出其他方法

阿拉:

foreach(obj.GetType().GetProperties()中的PropertyInfo属性)
{
if(prop.GetIndexParameters().Length>0)
{
//通过递增计数器直到引发异常,获取整数计数值
整数计数=0;
while(true)
{
尝试
{
prop.GetValue(obj,新对象[]{count});
计数++;
}
catch(targetingException){break;}
}
for(int i=0;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() );
        }
    }
static void Main()
{
object str=新字符串((“你好,世界”).ToArray();
过程(str);
Console.ReadKey();
}
静态无效过程(对象obj)
{
Type Type=obj.GetType();
PropertyInfo[]properties=type.GetProperties();
//如果此obj具有子属性,请将此过程应用于这些属性,而不是此属性。
如果(properties.Length>0)
{
foreach(PropertyInfo属性中的属性)
{
//如果是索引类型,则为每个
if(prop.GetIndexParameters().Length>0)
{
//获取整数计数值
//问题,如果它不是一个整数索引(字典?),如果它是多维的呢?
//只需要能够遍历索引属性中的每个值
整数计数=0;
while(true)
{
尝试
{
prop.GetValue(obj,新对象[]{count});
计数++;
}
catch(targetingException){break;}
}
for(int i=0;i
您可以使用查找索引属性参数的数量和类型


我认为要找到这些参数的“合法”值是什么,你无能为力,除非你“欺骗”并使用你可能拥有的关于该属性的内部信息。

索引器的getter与普通方法一样,只是它使用方括号,而不是圆括号。您不希望能够自动确定方法的可接受值范围,因此对于索引器来说是不可行的。

在索引属性中具有顺序索引号是不可能的。
索引属性不是数组。
反例:

Dictionary<int, bool> dictionary = new Dictionary<int, bool>();
dictionary[1] = true;
dictionary[5] = false;
Dictionary Dictionary=newdictionary();
字典[1]=真;
字典[5]=假;
根据类型,您通常有其他方法来获取可能的索引值,在本例中是
dictionary.Keys
。如果可能的话,我会按这个顺序试一下

  • 为类型本身实现
  • 如果有多个索引属性,则可以为每个索引属性实现相应的
    IEnumerable
    属性

  • 如果您没有有效值的规范,也没有询问有效值是什么的方法,那么您就很倒霉。

    索引器将被编译为方法。以下是一个例子:

    class IndexedData
    { 
        public double this[int index]
        {
            get { return (double)index; }
        }
    }
    
    它将被编译成如下内容:

    public double get_Item(int index)
    {
        return (double)index;
    }
    
    无法编译以下代码,因为类中有两个
    double get\u Item(int)
    方法。索引器是编译器的魔力

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

    mind设法进行了改进,还发现该测试代码自身引用存在无限循环(例如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() );
            }
        }
    
    静态无效处理(对象obj)
    {
    Type Type=obj.GetType();
    PropertyInfo[]properties=type.GetProperties();
    //如果此obj具有子属性,请将此过程应用于这些属性,而不是此属性。
    如果(properties.Length>0)
    {
    foreach(obj.GetType().GetProperties()中的PropertyInfo属性)
    {
    if(prop.PropertyType.FindInterfaces((t,c)=>t==typeof(IEnumerable),null).Length>0)
    {
    MethodInfo访问器=prop.G
    
        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() );
            }
        }
    
        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;
    }