2011-03-01 13 views
7

Sto provando a verificare se un determinato tipo è un delegato di azione, indipendentemente dalla quantità di parametri.Verificare se un determinato tipo è un delegato di azione

Il seguente codice è l'unico modo in cui so come farlo.

public static bool IsActionDelegate(this Type source) 
    { 
     return source == typeof(Action) || 
       source.IsOfGenericType(typeof(Action<>)) || 
       source.IsOfGenericType(typeof(Action<,>)) || 
       .... 
       source.IsOfGenericType(typeof(Action<,,,,,,,,,,,,,,,>)); 
    } 

IsOfGenericType() è un altro metodo di estensione della miniera, che fa quello che dice, controlla se il tipo è di un dato tipo generico.

Qualche suggerimento migliore?

risposta

5

Se siete appena dopo che i delegati che hanno un tipo di ritorno vuoto si possa effettuare le seguenti operazioni:

public static bool IsActionDelegate(Type sourceType) 
{ 
    if(sourceType.IsSubclassOf(typeof(MulticastDelegate)) && 
     sourceType.GetMethod("Invoke").ReturnType == typeof(void)) 
     return true; 
    return false; 
} 

questo non sarebbe distinguere tra Action e MethodInvoker (o altri delegati vuoto è per questo) però. Come altre risposte suggeriscono che potresti esaminare il nome del tipo, ma che odori un po ';-) Sarebbe utile se tu potessi chiarire per quale motivo vuoi identificare i delegati Action, per vedere quale approccio avrebbe funzionato meglio.

+1

Non so se la ricerca per nome è tanto male dato che il nome deriva da uno spazio dei nomi di libreria e non da un codice utente. –

+0

Grande intuizione, grazie! Sto cercando di creare un metodo Delegate.CreateDelegate generico. Per esempio. 'CreateDelegate > (owner, method);' È un work in progress quindi non so ancora se sarà possibile. Ma è per questo che devo analizzare il parametro generico e verificare quale tipo di delegato è previsto. –

+1

@Ritch - mi ricorda di controllare il tipo di browser in javascript anziché il controllo delle funzionalità - più tardi è molto più pulito. Forse ingiustificato in questo caso, ma non vorrei toccare il nome se non dovessi assolutamente farlo. – BrokenGlass

2

Questo sembra funzionare:

private static bool IsActionDelegate(this Type source) 
    { 
     var type = source.Name; 
     return source.Name.StartsWith("System.Action"); 
    } 

Esempio:

public static class Test 
{ 
    public static bool IsActionDelegate(this Type source) 
    { 
     var type = source.Name; 
     return source.Name.StartsWith("Action"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Action<string> one = s => { return; }; 
     Action<int, string> two = (i, s) => { return; }; 
     Func<int, string> function = (i) => { return null; }; 

     var single = one.GetType().IsActionDelegate(); 
     var dueces = two.GetType().IsActionDelegate(); 
     var func = function.GetType().IsActionDelegate(); 
    } 
} 

unico e dueces sono vere. func is false

+0

Ho pensato di controllare il nome prima, ma speravo che ci fosse una soluzione più pulita/più sicura. –

+0

Sì, sembrava ovvio. Ero solo curioso e questo è il motivo per cui l'ho scritto. Non penso che ci sia nulla di sicuro quando si fanno chiacchiere con tipi indipendenti e li si considera come equivalenti. –

2

Questi sono tipi distinti con niente in comune ma il loro nome. L'unica scorciatoia semi-ragionevole mi viene in mente:

public static bool IsActionDelegate(this Type source) 
{ 
    return source.FullName.StartsWith("System.Action"); 
} 

Certamente non fail-safe, ma chiunque dichiara i propri tipi nel namespace System merita qualche dolore e la sofferenza.

4
static Type[] _actionTypes = new[]{ 
     typeof(Action), 
     typeof(Action<>), 
     typeof(Action<,>), 
     typeof(Action<,,>), 
     typeof(Action<,,,>), 
     typeof(Action<,,,,>), 
     typeof(Action<,,,,,>), 
     typeof(Action<,,,,,,>), 
     typeof(Action<,,,,,,,>), 
     typeof(Action<,,,,,,,,>), 
     typeof(Action<,,,,,,,,,>), 
     typeof(Action<,,,,,,,,,,>), 
     typeof(Action<,,,,,,,,,,,>), 
     typeof(Action<,,,,,,,,,,,,>), 
     typeof(Action<,,,,,,,,,,,,,>), 
     typeof(Action<,,,,,,,,,,,,,,>), 
     typeof(Action<,,,,,,,,,,,,,,,>) 
    }; 
    private static bool IsAction(Delegate d) 
    { 
     return d != null && Array.IndexOf(_actionTypes, d.GetType()) != -1; 
    } 
+2

+1 per l'albero di natale :) Ma in questo caso prova un 'HashSet <>' .. – nawfal

+1

Tecnicamente il codice dovrebbe essere Array.IndexOf (_actionTypes, d.GetType(). GetGenericTypeDefinition())! = - 1. –

Problemi correlati