2010-10-08 14 views
7

Załóżmy, że mam klasę nieznaną do czasu wykonania. W czasie wykonywania otrzymuję odwołanie, x, typu Typ odwołujące się do Foo.GetType(). Tylko używając X i listy <>, czy mogę utworzyć listę typu Foo?Jak utworzyć instancję na liście <T>, ale wartość T jest nieznana do czasu wykonania?

Jak to zrobić?

+3

Coś, co powstrzymuje cię po prostu tworząc 'List '? – Flynn1179

+0

@ Flynn1179, daj mi zobaczyć, jak to robisz, proszę. – xport

+0

'List myList = nowa lista ();' – Flynn1179

Odpowiedz

19
Type x = typeof(Foo); 
Type listType = typeof(List<>).MakeGenericType(x); 
object list = Activator.CreateInstance(listType); 

Oczywiście nie należy spodziewać się żadnego typu bezpieczeństwa tutaj jako uzyskany lista typu object w czasie kompilacji. Korzystanie z List<object> byłoby bardziej praktyczne, ale nadal ograniczone, ponieważ typ Foo jest znany tylko w środowisku wykonawczym.

+0

Nice! Twoja odpowiedź sugeruje również (poprawnie), że praca z taką listą będzie dość niebezpieczna dla typu. Można oczywiście zadeklarować 'list' jako typ (nietypowy)' IList' lub 'ICollection' (zamiast tylko' obiektu'), któremu towarzyszy odpowiednia obsada powrotu 'Activator.CreateInstance' wartości, tak aby możliwy był ograniczony sposób pracy z 'list' jako kolekcją. – stakx

+2

Jeśli utworzysz typy w czasie wykonywania, upewnij się, że nie ma żadnego bezpieczeństwa podczas kompilacji. – Frank

0

coś takiego:

Activator.CreateInstance (typeof (Lista <>) MakeGenericType (typ)).

11

Pewnie można:

var fooList = Activator 
    .CreateInstance(typeof(List<>) 
    .MakeGenericType(Foo.GetType())); 

Problem tutaj jest to, że fooList typu object, więc nadal musisz go rzucić w typ "użyteczny". Ale jak wyglądałby ten typ? Ponieważ struktura danych obsługująca dodawanie i wyszukiwanie obiektów typu TList<T> (lub raczej IList<>) nie jest kowariantna w T, więc nie można przesłać List<Foo> do List<IFoo>, gdzie Foo: IFoo. Możesz rzucić go do IEnumerable<T>, który jest kowariancyjny w T.

Jeśli używasz C# 4.0, możesz również rozważyć przesłanie fooList do dynamic, dzięki czemu możesz przynajmniej użyć go jako listy (np. Dodawać, wyszukiwać i usuwać obiekty).

Biorąc pod uwagę to wszystko i fakt, że nie masz żadnego rodzaju bezpieczeństwa podczas tworzenia typów w czasie wykonywania, po prostu użycie List<object> jest prawdopodobnie najlepszym/najbardziej pragmatycznym sposobem postępowania w tym przypadku.

Powiązane problemy