2013-07-05 17 views
6

Mam zaludnionych listę obserwacji z obiektów typu AnonymousTypeLista <object> Odlewanie do listy AnonymousTypes

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

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

Moim problemem jest to, że nie mogę zrobić to Stronly wpisane zrobić coś takiego:

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

Jednakże, jest to możliwe na tej liście:

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

Can rzucam pierwsza lista, aby zachowywać się jak druga lista? Chcę móc używać wyrażeń lambda na właściwościach, które pokazałem powyżej.

+3

Dlaczego masz '' Lista gdy jego '' Lista ? –

+1

@TimSchmelter Ponieważ 'AnonymousType' jest typem' obiektu'. Nie ma czegoś takiego jak typ danych "anonimowy". Dobrze? – Johan

+0

Typy anonimowe mają tylko właściwości tylko do odczytu. – Romoku

Odpowiedz

9

Można skorzystać z leków generycznych i rodzaj wnioskowania, aby utworzyć listę dla Ciebie:

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

Wykorzystanie takich jak:

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

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

Naturalnie nie będzie w stanie zrobić wiele z to. Nigdy nie będziesz w stanie silnie wpisać go w swoim kodzie do niczego innego niż var lub zwrócić go ze swojej metody lub czegokolwiek, czego normalnie nie mógłbyś zrobić z anonimowymi typami. Jeśli chcesz zrobić więcej, po prostu musisz ugryźć (mały) punktor i zdefiniuj klasę dla swojego anonimowego typu.


Rereading pytanie, nadal można wykonać kwerendy LINQ na tablicy:

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

Więc jeśli nie modyfikują go (powiedzmy za pośrednictwem standardowych List<T> operacji jak Add lub Remove), to nie ma powodu, aby Konwertuj go na List<T>.

Zdaję sobie sprawę, że być może nadal będziesz w stanie go przekazać (z jakiegoś powodu) i nadal wykonywać operacje bez znajomości jego anonimowego typu. W takim przypadku mógłby traktować go jako dynamic i wykonywać operacje w czasie wykonywania, ale stracisz żadnej intellisense/strong pisanie że chcesz normalnie mieć z typem anonimowego:

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

ostatnia metoda jak podkreślił Tim Schmelter to dzięki wykorzystaniu CastByExample Jon Skeet, ale rozszerza się przekształcić swoją kolekcję o metodę rozszerzenia:

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 }}; 
} 

z wykorzystaniem takich jak:

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

ta wykorzystuje fakt, że w ciągu samego zespołu na anonimowe typy deklarowanej o tych samych nazwach parametrów, typów i zamówienie skompilować do tego samego typu.To nie zadziała, jeśli musisz zadzwonić pod numer CreateAnonymousData spoza bieżącego zespołu i musisz zachować sygnaturę swojego anonimowego typu foo wszędzie, gdzie go używasz (dodaj/zmień jego sygnaturę, musisz musi zaktualizować to wszędzie, gdzie jesteś użyj go lub będziesz miał zły czas).

Ale myślę, że teraz staje się bardziej jasne, że najlepszym rozwiązaniem jest po prostu zdefiniowanie reprezentacji klasowej swojego anonimowego typu.

+0

Całkiem dosłownie 1 sekundę za mną na 'dynamic' :-p –

+0

Nice, ale problem pozostaje jednak. Chcę, aby zajęła się ogólną listą obiektów jako parametrem i zwraca 'var someList = new [] {new {foo = 1}};' – Johan

+0

Haha, yeah @ByteBlast. Odpowiada mi za to, że wrzuciłem do edycji nieco o wykonaniu LINQ na tablicach przed opublikowaniem mojej edycji! :) –

4

Można użyć 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

Można to zrobić o krok dalej metodą rozszerzenia podobną do metody "Cast (T)". użycie: 'someList.CastByExample (example) .ToList();' – Romoku

Powiązane problemy