2013-04-06 6 views
7

Al momento sto facendo questo (// edit: che è totalmente stupido come non c'è serie che consequentily numeri relativi elementi nello stesso modo in cui ho fatto il mio dizionario di ieri):Un modo più elegante per ottenere in modo dinamico il tipo di azione <> generico per il conteggio dei parametri?

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

E da qualche altra parte. ..

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

dove meth è un metodo.

C'è un modo più elegante per farlo? O devo definire una mappa come questa per ottenere il tipo corretto di azione <> che corrisponde al conteggio dei parametri?

+0

Sarebbe utile conoscere lo scopo. Se viene data una migliore idea del problema più ampio che stai cercando di risolvere, è più probabile che tu possa produrre una risposta di qualità per te. – konkked

risposta

10

EDIT:

BTW, Sapete di Expression.GetActionType?

Crea un oggetto Type che rappresenta un tipo System.Action delegato generico con argomenti di tipo specifici.

Utilizzando questo metodo, si potrebbe fare:

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

Altri modi:

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

Ma non c'è davvero niente di sbagliato con il vostro approccio davvero; essere il più esplicito possibile è spesso una scelta migliore quando si tratta di riflettere.

Inoltre, ecco un altro modo elegante per costruire la vostra carta:

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

GetActionType funziona come un fascino. Molte grazie! –

1

È possibile utilizzare matrice invece di dizionario, in realtà è numerato da 0 a 8, basta usare array di tipi e di accedervi con l'indice.

+0

A parte il fatto che la risposta di Ani risolve perfettamente il mio problema, questo è un caso classico di auto-facepalm: ovviamente ero così di fretta, ieri, che ho perso la foresta per gli alberi ... Grazie per questa intuizione illuminante ! –

Problemi correlati