2012-06-25 17 views
5

Ho un IEnumerable<KeyValuePair<string,string>>, dal quale vorrei, idealmente, un oggetto anonimo che ha le chiavi come nomi di proprietà e i valori come valori di proprietà.Converti KeyValuePair in tipo anonimo in una query LINQ

Ho provato varie espressioni di selezione (nessuna delle quali nemmeno compilata ...) e un approccio utilizzando ExpandoObject (vedi sotto), ma senza successo. C'è un buon modo per farlo? Se possibile, vorrei evitare un'iterazione esplicita extra sulla raccolta (ad esempio, fare tutto con una dichiarazione LINQ di qualche tipo).

Questo è quello che ho provato finora. Spero che chiarisce, inoltre, quello che sto cercando di fare:

var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>> 

dynamic o = new ExpandoObject(); 
foreach (var kvp in kvps) 
{ 
    o.Add(kvp); 
} 

Questo è OK al momento della compilazione, ma a tempo di esecuzione ottengo un YSOD affermando 'System.Dynamic.ExpandoObject' non contiene una definizione per ' Aggiungi' - Credo che funziona al momento della compilazione perché o è dinamico, in modo che il compilatore non può sapere se un metodo .Add() è stato aggiunto ad esso da quando è stato istanziato. La cosa strana è che sul MSDN documenation page for ExpandoObject.Add() è elencato come uno dei numerosi "metodi di interfaccia esplicitamente implementati".

Non è necessario per me ottenere questo in un oggetto dinamico: ho solo bisogno di ottenere qualcosa che abbia nomi e valori di proprietà in base alle chiavi e ai valori delle coppie chiave-valore.

Aggiornamento: Bene, questo è imbarazzante. Risulta che anche questo era qualcosa di un problema XY.

Sto provando a renderlo a JSON utilizzando le funzionalità integrate di ASP.NET MVC, semplicemente restituendo Json(data) nel mio controller. Le risposte tutti hanno lavorato molto bene a fare quello che ho chiesto, ma quando passo questo oggetto come data io ancora non si ottiene quello che voglio:

// What I get: 
[ 
    { Key: 'firstkey', Value: 'FirstValue' }, 
    { Key: 'secondKey', Value: 'secondValue' } 
] 

// What I want: 
{ firstKey: 'FirstValue', secondKey: 'secondValue' } 

A quanto pare, un ExpandoObject con le proprietà rilevanti aggiunto non l'ha fatto tagliare - è stata lanciata a un dizionario prima del rendering ...

+1

E sì, ho visto [questa domanda] (http://stackoverflow.com/questions/4685575/converting-a-keyvaluepair-collection-in-to-anonymous-type). Era davvero un [problema XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), che è stato risolto senza aiutarmi. –

risposta

4

ExpandoObject implementa in modo esplicito IDictionary<string, object> - quindi è necessario lanciarlo ad una prima:

var kvps = getProps(); 
dynamic o = new ExpandoObject(); 
var dict = o as IDictionary<string, object>; 
foreach (var kvp in kvps) 
{ 
    dict.Add(kvp.Key, kvp.Value); 
} 

Ora è possibile utilizzare o come ci si aspetterebbe:

var example = o.YourKey; 

Sto provando a renderlo a JSON utilizzando le funzionalità integrate di ASP.NET MVC, semplicemente restituendo Json (dati) nel mio controller.

Interessante.

Per fare ciò, serializzate un dizionario, non un ExpandoObject. Il serializzatore JSON di MVC 3 lo fa già con un dizionario.Tutto quello che dovete fare è convertire il vostro IEnumerable<KeyValuePair<string, object>> a un dizionario:

var kvps = getProps(); 
var dictionary = kvps.ToDictionary(k => k.Key, v => v.Value); 
return Json(dictionary, JsonRequestBehavior.AllowGet); //take out allow get if you don't need it. 

Nessun dinamiche richieste.

+0

Grazie! Tuttavia, ero un po 'troppo veloce per formulare il mio problema - per favore vedi il mio aggiornamento ... –

+0

@TomasLycken Aggiornato. – vcsjones

+0

Fantastico! Grazie mille! =) –

6

è necessario utilizzare il ExpandoObject come IDictionary<string, object> durante il popolamento è:

var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>> 

IDictionary<string, object> o = new ExpandoObject(); 
foreach (var kvp in kvps) 
{ 
    // Or use Add(kvp.Key, kvp.Value), if you want 
    o[kvp.Key] = kvp.Value; 
} 

dynamic d = o; 
// Now you can use the properties 
+0

Questo mi dà un errore di compilazione sulla prima riga ('IDictionary o = nuovo ExpandoObject();'), ma dato che sei tu, suppongo che il compilatore sia sbagliato. Suppongo che pensi che dovrebbe essere 'IDictionary ' - Dirò immediatamente che hai detto di farlo in questo modo. –

+0

Lì, ora funziona =) –

+0

... ma non interamente. Si prega di consultare il mio aggiornamento. –

1

credo che bisogna lanciare l'oggetto Expando a IDictionary e chiamare Aggiungere (stringa, oggetto)

Problemi correlati