簡體   English   中英

迭代索引屬性(反射)

[英]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 如果你的類型可以,我會嘗試這個順序

  1. 為類型本身實現IEnumerable<T>
  2. 如果您有多個索引屬性,則可以為每個索引屬性實現相應的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM