2012-03-27 15 views
56

Ho una classe contenente diverse proprietà (tutte sono stringhe se fa alcuna differenza).
Ho anche una lista, che contiene molte diverse istanze della classe.C# foreach (proprietà nell'oggetto) ... Esiste un modo semplice per farlo?

Durante la creazione di alcuni test di unità per le mie classi ho deciso che volevo collegare attraverso ogni oggetto nella lista e poi scorrere ogni proprietà di tale oggetto ...

ho pensato di fare questo sarebbe il più semplice. ..

foreach (Object obj in theList) 
{ 
    foreach (Property theProperties in obj) 
    { 
     do some stufff!!; 
    } 
} 

Ma questo non ha funzionato! :( ottengo questo errore ...

"foreach non può operare su variabili di tipo 'Application.Object' perche 'Application.Object' non contiene una definizione pubblica per 'GetEnumerator'"

fa qualcuno sa di un modo di fare questo senza tonnellate di se e loop o senza entrare in qualcosa di troppo complesso

+4

In futuro, non dire "Non funziona" in una domanda. Invece, specifica il problema che stai riscontrando (errore del compilatore, ecc.). Grazie! –

+0

Aggiornato! Grazie per il testa a testa Robert – Jammerz858

risposta

91

dare una prova:?

foreach (PropertyInfo propertyInfo in obj.GetType().GetProperties()) 
{ 
    // do stuff here 
} 

Inoltre si ricorda che Type.GetProperties() ha un sovraccarico che accetta un set di flag di associazione in modo da poter filtrare le proprietà su un criterio diverso come il livello di accessibilità, vedere MSDN per ulteriori dettagli: Type.GetProperties Method (BindingFlags) Ultimo ma non meno importante non dimenticare di aggiungere il riferimento all'assembly "system.Reflection".

Ad esempio per risolvere tutte le proprietà pubbliche:

foreach (var propertyInfo in obj.GetType() 
           .GetProperties(
             BindingFlags.Public 
             | BindingFlags.Instance)) 
{ 
    // do stuff here 
} 

prega fatemi sapere se questo funziona come previsto.

+1

Una volta che hai un handle sulle proprietà degli oggetti, c'è comunque l'acquisizione del valore di ogni proprietà? Ad esempio, un nome o un codice postale, ad esempio – JsonStatham

2

utilizzare la reflection per fare questo

SomeClass A = SomeClass(...) 
PropertyInfo[] properties = A.GetType().GetProperties(); 
12

Your'e quasi, basta per ottenere le proprietà dal tipo, piuttosto che aspettare le proprietà siano accessibili sotto forma di una sacca di raccolta o di proprietà :

var property in obj.GetType().GetProperties() 

Da lì you can access like so:

property.Name 
property.GetValue(obj, null) 

Wi th GetValue il secondo parametro ti consentirà di specificare i valori dell'indice, che funzionerà con le proprietà che restituiscono le raccolte - poiché una stringa è una raccolta di caratteri, puoi anche specificare un indice per restituire un carattere se necessario.

+0

ho turbato qualcuno? Sono aperto a sapere cosa c'è che non va, altrimenti non potrei mai imparare. –

+0

Probabilmente hai ottenuto il downvote quando il tuo codice era sbagliato (prima del tuo ninja edit). –

13

Certo, nessun problema:

foreach(object item in sequence) 
{ 
    if (item == null) continue; 
    foreach(PropertyInfo property in item.GetType().GetProperties()) 
    { 
     // do something with the property 
    } 
} 
+0

perché hai aggiunto questa linea? 'if (item == null) continua;' personalmente, penso che se hai ottenuto un oggetto nullo a quel punto, qualcosa è andato storto molto prima e che è dove dovrebbe essere la convalida, o sbaglio? – Dementic

+0

@Dementic: Certo, potremmo dire che la sequenza è necessaria per contenere riferimenti non nulli. –

20

è possibile scorrere tutte le proprietà non indicizzate di un oggetto come questo:

var s = new MyObject(); 
foreach (var p in s.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) { 
    Console.WriteLine(p.GetValue(s, null)); 
} 

Dal GetProperties() rendimenti indicizzatori così come le proprietà semplici, è necessario un filtro aggiuntivo prima di chiamare GetValue per sapere che è sicuro passare il null come secondo parametro.

Potrebbe essere necessario modificare ulteriormente il filtro per eliminare le proprietà di sola scrittura e altrimenti inaccessibili.

+0

+1 per fare solo qualcosa con le proprietà che possono essere effettivamente utilizzate - potresti anche voler filtrare le proprietà di sola scrittura. – hvd

+0

@hvd È un eccellente punto sulle proprietà di sola scrittura! Mi sono quasi dimenticato di loro. Il mio codice andrà in crash se incontra una proprietà con getter 'null', ma sono sicuro che OP capirà come ottenere solo le proprietà di cui ha bisogno. – dasblinkenlight

+1

ha votato per mostrare come ottenere il valore –

0

Una piccola parola di cautela, se "fare un po 'di cose" significa aggiornare il valore della proprietà effettiva che si visita E se c'è una proprietà di tipo struct lungo il percorso dall'oggetto root alla proprietà visitata, la modifica apportata sulla proprietà non si rifletterà sull'oggetto radice.

Problemi correlati