2013-07-05 11 views
6

ho popolato la lista follow con oggetti di tipo AnonymousTypeFusioni Lista <object> alla lista AnonymousTypes

List<object> someList = new List<object>(); 

someList.Add(new { foo = 1 }); 

Il mio problema è che non riesco a farlo stronly digitato per fare qualcosa di simile:

someList.Where(x=> x.foo == 1); 

Tuttavia, è possibile in questa lista:

var someList = new[] { new { foo = 1 } }; 

Posso lanciare il mio primo elenco per farlo comportarsi come il secondo elenco? Voglio essere in grado di usare espressioni lambda sulle proprietà come ho mostrato sopra.

+3

perché hai un '' lista quando è un elenco '' ? –

+1

@TimSchmelter Perché 'AnonymousType' è un tipo di' oggetto'. Non esiste un tipo di dati 'anonimo '. Destra? – Johan

+0

I tipi anonimi hanno solo proprietà di sola lettura. – Romoku

risposta

9

È possibile usufruire di farmaci generici e inferenza di tipo per creare l'elenco per voi:

public static List<T> CreateAnonymousList<T>(params T[] entries) 
{ 
    return new List<T>(entries); 
} 

Uso come:

var someList = CreateAnonymousList(new { foo = 1 }, new { foo = 2 }, new { foo = 1 }); 

someList.Where(x => x.foo == 1); 

Naturalmente non sarà in grado di fare molto di con esso. Non sarai mai in grado di scriverlo con forza nel tuo codice a un valore diverso da var o restituirlo dal tuo metodo o qualsiasi cosa che normalmente non potresti fare con i tipi anonimi. Se vuoi fare di più, devi solo mordere il (piccolo) proiettile e definire una classe per il tuo tipo anonimo.


Rileggendo la tua domanda, è ancora possibile eseguire query LINQ su un array:

var someArray = new[]{new { foo = 1 }, new { foo = 2 }, new { foo = 1 }}; 
someArray.Where(x => x.foo == 1) 

Quindi, a meno che non si sta modificando esso (dite tramite standard di List<T> operazioni come Add o Remove) allora non c'è motivo di devi convertirlo in un List<T>.

Mi rendo conto che forse si desidera essere ancora in grado di restituirlo (per qualche motivo) e continuare a fare operazioni su di esso senza conoscerne il tipo anonimo. In questo caso si potrebbe trattarlo come dynamic ed eseguire le operazioni in fase di esecuzione, ma si perde qualsiasi intellisense/strong digitazione che normalmente si ha con il tipo anonimo:

List<dynamic> someDynamicList = new List<dynamic>() {new { foo = 1 }, new { foo = 2 }, new { foo = 1 }}; 
someDynamicList.Where(x => x.foo == 1) 

Un ultimo metodo come sottolineato da Tim Schmelter sfruttando CastByExample di Jon Skeet, ma esteso a convertire la vostra collezione con un metodo di estensione:

public static IEnumerable<T> CastByExample<T>(this IEnumerable source, T example) 
{ 
    foreach(object entry in source) 
     yield return (T)entry; 
} 

public static IEnumerable CreateAnonymousData() 
{ 
    return new[]{new { foo = 1 }, new { foo = 2 }, new { foo = 1 }}; 
} 

con l'utilizzo come:

var anonymousData = CreateAnonymousData(); 
var typedAnonymousData = anonymousData.CastByExample(new { foo = 1 }); 
typedAnonymousData.Where(x => x.foo == 1); 

Questa sfrutta il fatto che all'interno della stessa assemblea , tipi anonimi dichiarate con gli stessi nomi dei parametri, i tipi, e fine compilare allo stesso tipo.Questo non funzionerà se devi chiamare il tuo CreateAnonymousData dall'assemblaggio corrente e devi mantenere la firma del tuo tipo anonimo foo ovunque lo usi (aggiungi/modifica la sua firma, tu devi aggiornalo ovunque tu usalo o avrai un brutto momento).

Ma penso che stia diventando più chiaro ora che la soluzione migliore è semplicemente definire una rappresentazione di classe del tipo anonimo.

+0

Abbastanza letteralmente 1 secondo dietro di me su 'dynamic' :-p –

+0

Bello, ma il problema rimane comunque. Voglio che prenda la lista degli oggetti generici come parametro e restituisca 'var someList = new [] {new {foo = 1}};' – Johan

+0

Haha, yeah @ByteBlast. Mi serve per includere nella mia modifica il bit sull'esecuzione di LINQ sugli array prima di pubblicare la mia modifica! :) –

4

È possibile utilizzare Jon Skeets' CastByExample:

public static T CastByExample<T>(object input, T example) 
{ 
    return (T)input; 
} 

List<object> someList = new List<object>() { 
    new { foo = 1 },new { foo = 2 },new { foo = 3 } 
}; 

var example = new { foo = 0 }; 

foreach (object obj in someList) 
{ 
    var x = CastByExample(obj, example); 
    Console.WriteLine("Foo: " + x.foo); 
} 
+1

Questo potrebbe essere fatto un passo avanti con un metodo di estensione simile a 'Cast (T)'. utilizzo: 'someList.CastByExample (esempio) .ToList();' – Romoku

Problemi correlati