2012-02-24 11 views
30

Come determinare se una proprietà è un tipo di matrice.Determinare se una proprietà è un tipo di matrice per riflessione

Esempio:

public bool IsPropertyAnArray(PropertyInfo property) 
{ 
    // return true if type is IList<T>, IEnumerable<T>, ObservableCollection<T>, etc... 
} 
+1

Quindi, vuoi dire, se la proprietà è una collezione? Le cose che corrispondono al tuo commento non sono matrici. –

+2

Probabilmente intendevi 'IEnumerable' invece di' IEnumerator'? – Groo

+0

@ Ben: Beh, gli array corrispondono ai suoi criteri (IList e IEnumerable ), ma non tutte le cose che corrispondono ai suoi criteri sono array.:) – Sven

risposta

54

Sembra che tu stia facendo due domande diverse: se un tipo è un array (ad es. string[]) o qualsiasi tipo di raccolta.

Per il primo, è sufficiente controllare property.PropertyType.IsArray.

Per quest'ultimo, è necessario decidere qual è il criterio minimo a cui si desidera conformare un tipo. Ad esempio, è possibile verificare lo IEnumerable non generico utilizzando typeof(IEnumerable).IsAssignableFrom(property.PropertyType). Puoi anche usarlo per interfacce generiche se conosci il tipo effettivo di T, ad es. typeof(IEnumerable<int>).IsAssignableFrom(property.PropertyType).

È possibile controllare il generico IEnumerable<T> o qualsiasi altra interfaccia generica senza conoscere il valore di T controllando se property.PropertyType.GetInterface(typeof(IEnumerable<>).FullName) non è null. Si noti che non ho specificato alcun tipo per T in quel codice. Si può fare lo stesso per IList<T> o di qualsiasi altro tipo che ti interessa

Per esempio si potrebbe utilizzare il seguente se si desidera controllare per il generico IEnumerable<T>:.

public bool IsPropertyACollection(PropertyInfo property) 
{ 
    return property.PropertyType.GetInterface(typeof(IEnumerable<>).FullName) != null; 
} 

Array anche implementare IEnumerable, quindi restituiranno anche true da quel metodo.

+1

Questa implementazione avrebbe perso "raccolte di vecchia scuola", ereditate da .Net 1 e che implementa IEnumerable ma non la versione generica IEnumerable . Sono sempre meno usati, ma alcuni API li aspettano e sono davvero un problema. – Falanwe

+1

@Fananwe: Quindi utilizzare il primo metodo che ho menzionato, che controlla l'IEnumerable non generico. Dipende davvero dalle sue esigenze che è il migliore. – Sven

+1

Provo il tuo metodo con una proprietà che è una stringa e il metodo restituisce true ... Sai perché? – Melursus

11

Se volete sapere se la proprietà è un array, in realtà è molto semplice:

property.PropertyType.IsArray; 

modificare

Se vuoi sapere se è un tipo che implementa IEnumerable, come tutti i "tipi di raccolta", non è nemmeno complicato:

return property.PropertyType.GetInterface("IEnumerable") != null; 
+0

Non sono sicuro che sia ciò che l'OP voleva davvero (ma ammetto che la denominazione è un po 'fuorviante). Il tipo personalizzato che implementa 'IList ' restituirà false da questa proprietà. – Groo

+0

in effetti, ho letto male la domanda inizialmente. Ho modificato la mia risposta per includere qualsiasi IEnumerable – Falanwe

+2

@Falanwe: 'IsSubclassOf' non funziona per le interfacce, solo le classi di base. – Sven

2
public static bool IsGenericEnumerable(Type type) 
    { 
     return type.IsGenericType && 
      type.GetInterfaces().Any(
      ti => (ti == typeof (IEnumerable<>) || ti.Name == "IEnumerable")); 
    } 

    public static bool IsEnumerable(Type type) 
    { 
     return IsGenericEnumerable(type) || type.IsArray; 
    } 
0

Per me il seguente non funziona,

return property.PropertyType.GetInterface(typeof(ICollection<>).FullName) != null; 

seguente era lavorando,

typeof(ICollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()) 

Questo è il modo di scelta rapida per controllare ICollection<IInterface> o ICollection<BaseClassInTree>

var property = request as PropertyInfo; 

property.PropertyType.IsGenericType && (typeof(ICollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition())) && typeof().IsAssignableFrom(property.PropertyType.GenericTypeArguments[0]) 
16

Exclu ding String classe poichè si qualifica come raccolta perché implementa IEnumerable<char>.

public bool IsPropertyACollection(this PropertyInfo property) 
{ 
    return (!typeof(String).Equals(property.PropertyType) && 
     typeof(IEnumerable).IsAssignableFrom(property.PropertyType)); 
} 
+0

typeof (String) era l'assegno che mi mancava –

Problemi correlati