2013-04-06 11 views
7

W tej chwili robię to (// EDIT: co jest całkowicie głupi jak tam tablicę, która consequentily numery swoich produktów w taki sam sposób, odbyłem Słownik wczoraj):Bardziej elegancki sposób dynamicznego generowania typu akcji <> według liczby parametrów?

Dictionary<int, Type> genericMap = new Dictionary<int, Type> 
     { 
      { 0, typeof(Action) }, 
      { 1, typeof(Action<>) }, 
      { 2, typeof(Action<,>) }, 
      { 3, typeof(Action<,,>) }, 
      { 4, typeof(Action<,,,>) }, 
      { 5, typeof(Action<,,,,>) }, 
      { 6, typeof(Action<,,,,,>) }, 
      { 7, typeof(Action<,,,,,,>) }, 
      { 8, typeof(Action<,,,,,,,>) }, 
     }; 

i gdzieś indziej. ..

var parms = meth.GetParameters(); 
dType = genericMap[parms.Length].MakeGenericType(parms.Select(p => p.ParameterType).ToArray()); 

gdzie meth jest MethodInfo.

Czy istnieje bardziej elegancki sposób na zrobienie tego? Czy muszę zdefiniować taką mapę, aby dynamicznie uzyskać prawidłowy typ Action <, który odpowiada liczbie parametrów?

+0

Pomocne byłoby poznanie celu. Jeśli masz lepszy pomysł na większy problem, który próbujesz rozwiązać, najprawdopodobniej wytworzysz dla ciebie odpowiednią odpowiedź. – konkked

Odpowiedz

10

EDIT:

BTW Czy znasz Expression.GetActionType?

Tworzy obiekt, który reprezentuje typ rodzajowy System.Action delegat typ, który ma konkretne argumenty typu.

Stosując tę ​​metodę, można zrobić:

dType = Expression.GetActionType(parms.Select(p => p.ParameterType).ToArray()); 

Inne sposoby:

var parms = meth.GetParameters(); 

int numArgs = parms.Length; 

if(numArgs == 0) 
{ 
    dType = typeof(Action); 
}  
else 
{ 
    var rawType = Type.GetType("System.Action`" + numArgs); 
    dType = rawType.MakeGenericType(parms.Select(p => p.ParameterType).ToArray()); 
} 

Ale tam naprawdę nic złego w swoim podejściu naprawdę; bycie tak jawnym, jak to możliwe, jest często lepszym wyborem, jeśli chodzi o refleksję.

Również tutaj jest inny fantazyjny sposób budowania mapy:

typeof(Action).Assembly 
       .GetExportedTypes() 
       .Where(type => type.FullName.StartsWith("System.Action") 
            && type.IsSubclassOf(typeof(Delegate))) 
       .ToDictionary(type => type.GetGenericArguments().Length) 
+0

GetActionType działa jak urok. Wielkie dzięki! –

1

Można użyć tablicę zamiast słownika, to faktycznie o numerach od 0 do 8, wystarczy użyć wachlarz typów i dostęp do nich z indeksu.

+0

Pomijając fakt, że odpowiedź Ani rozwiązuje mój problem doskonale, jest to klasyczny przypadek self-facepalm: oczywiście tak bardzo się śpieszyłem, wczoraj, że tęskniłem za lasem dla drzew ... Dzięki za ten pouczający wgląd ! –

Powiązane problemy