2011-01-12 14 views
6

Próbuję utworzyć typ, który odwołuje się do tablicy typu ogólnego, bez określania typ rodzajowy. To znaczy, chciałbym zrobić odpowiednik Type.GetType("T[]").Uzyskiwanie typu tablicy T bez określania T - Type.GetType ("T []")

Już wiem, jak to zrobić z typem innym niż tablicowy. Na przykład.

Type.GetType("System.Collections.Generic.IEnumerable`1") 
// or 
typeof(IEnumerable<>) 

Oto przykładowy kod, który odtwarza problem.

using System; 
using System.Collections.Generic; 

public class Program 
{ 
    public static void SomeFunc<T>(IEnumerable<T> collection) { } 

    public static void SomeArrayFunc<T>(T[] collection) { } 

    static void Main(string[] args) 
    { 
     Action<Type> printType = t => Console.WriteLine(t != null ? t.ToString() : "(null)"); 
     Action<string> printFirstParameterType = methodName => 
      printType(
       typeof(Program).GetMethod(methodName).GetParameters()[0].ParameterType 
       ); 

     printFirstParameterType("SomeFunc"); 
     printFirstParameterType("SomeArrayFunc"); 

     var iEnumerableT = Type.GetType("System.Collections.Generic.IEnumerable`1"); 
     printType(iEnumerableT); 

     var iEnumerableTFromTypeof = typeof(IEnumerable<>); 
     printType(iEnumerableTFromTypeof); 

     var arrayOfT = Type.GetType("T[]"); 
     printType(arrayOfT); // Prints "(null)" 

     // ... not even sure where to start for typeof(T[]) 
    } 
} 

Wyjście jest:

System.Collections.Generic.IEnumerable`1[T] 
T[] 
System.Collections.Generic.IEnumerable`1[T] 
System.Collections.Generic.IEnumerable`1[T] 
(null) 

Chciałbym poprawić ten ostatni "(null)".

ta zostanie wykorzystana, aby uzyskać przeciążenie funkcji poprzez odbicia podając sygnaturę metoda:

var someMethod = someType.GetMethod("MethodName", new[] { typeOfArrayOfT }); 
// ... call someMethod.MakeGenericMethod some time later 

Już dostał mój kod działa głównie poprzez filtrowanie wynik GetMethods(), więc jest to bardziej ćwiczenia w zakresie wiedzy i zrozumienia.

Odpowiedz

8

Proste:

var arrayOfT = typeof(IEnumerable<>).GetGenericArguments()[0].MakeArrayType(); 
+0

Nice. Nie pomyślałbym o tym osobiście. –

+0

+1: Nadal nieco bałaganiarski (ponieważ 'IEnumerable <>' był tylko przykładem - nie ma to żadnego znaczenia w moim kodzie docelowym), ale działa to jak urok :) Czy istnieje lepszy sposób na uzyskanie 'Type.GetType (" T ")'? –

+0

To jednak nie pomoże ci związać się z metodami, ponieważ parametr typu T w IEnumerable nie jest tym samym T, co w SomeFunc (). – phoog

1

Jak na ten temat?

Type MakeArrayType(Type elementType, int rank) 
{ 
    return elementType.MakeArrayType(rank); 
} 

przykładów:

var x = MakeArrayType(typeof(string), 1); // x == typeof(string[]) 
var y = MakeArrayType(typeof(float), 4); // y == typeof(float[,,,]) 

EDIT

Jonathan Dickinson wskazuje elementType.MakeArrayType (1), nie zwraca tego samego typu jak elementType.MakeArrayType(). Nie będę modyfikował oryginalnej próbki kodu, ponieważ w każdym razie nie odpowiada na pytanie.

Różnica między Type.MakeArrayType (1) i Type.MakeArrayType() jest taka, że ​​druga zwraca typ wektorowy - który jest koniecznie oparty na 1-wymiarach i od zera - podczas gdy pierwszy zwraca wielowymiarowy typ tablicy, który zdarza się, że ma rangę 1. Instancje zwracanego typu niekoniecznie muszą być oparte na zera.

Typ wektorowy jest oznaczony parą nawiasów kwadratowych (na przykład System.Int32[]), natomiast typ tablicy 1 rangu jest oznaczony parą nawiasów kwadratowych zawierających gwiazdkę (na przykład System.Int32[*]).

+0

To jest blisko, ale nie do końca tego, czego chcę. Potrzebuję konkretnie T []. Zobacz, dlaczego chcę użyć tego typu na dole pytania. –

+2

Haha, jest 'MakeArrayType (typeof (ciąg), 1)' * naprawdę * lepiej niż 'typeof (ciąg) .MakeArrayType (1)'? –

+0

@ Dan Tao: Nieszczególnie – phoog

Powiązane problemy