Alex Rivera | Logout

iterating through an indexed property (Reflection)

Asked 2010-11-24T15:08:14.447
14

I want to itterate over an indexed property that I only have access to via reflection,

but ( and I say this in the full knowledge that there's probably an embarrassingly simple answer, MSDN/Google fail =/ ) I cannot find/think of a way besides incrementing a counter over the PropertyInfo.GetValue(prop, counter) until the TargetInvocationException is thrown.

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

now, there are some issues with this... very ugly.. solution..

what if it's multi-dimensional or not indexed by integers for example...

heres the test code I'm using to try and get it working if anyone needs it. If anyone's interested I'm making a custom caching system and .Equals doesn't cut it.

    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
              
Edit
Report

1 Answer

3

Managed to make an improvement, mind, also found out that this test code suffers from infinite loops for self references (Array.Syncroot for example)

In a nutshell it now finds things that inherit from IEnumerable (which is most indexed things) and use a foreach loop on those and coupled with the knowledge that the existing (ugly) code works for strings, it's now allot more thorough then it used to be...

glad but disapointed that there doesn't seem to be a nice answer.

Thanks for the help everyone


Updated test code if someone finds themselves in a similar position

    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 ( Targe
answered 2010-11-24T17:06:10.300

Your Answer