2011-03-01 18 views
7

Estoy tratando de verificar si un tipo determinado es un delegado de acción, independientemente de la cantidad de parámetros.Comprobando si un cierto tipo es un delegado de Acción

El siguiente código es la única forma en que sé cómo hacerlo.

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

IsOfGenericType() es otro método de extensión de mina, que hace lo que dice, se comprueba si el tipo es del tipo genérico dado.

¿Alguna mejor sugerencia?

Respuesta

5

Si son sólo después de que los delegados que tienen un tipo de retorno void que podría hacer lo siguiente:

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

Esto no distinguiría entre Action y MethodInvoker (u otros delegados de vacío para el caso) sin embargo. Como otras respuestas sugieren que podrías examinar el nombre del tipo, pero que huele un poco ;-) Ayudaría si pudieras aclarar por qué razón quieres identificar a los delegados Action, para ver qué enfoque funcionaría mejor.

+1

No sé si buscar por nombre es tan malo dado que el nombre proviene de un espacio de nombre de la biblioteca y no de un código de usuario. –

+0

¡Gran idea, gracias! Estoy tratando de hacer un método delegate.CreateDelegate genérico. P.ej. 'CreateDelegate > (propietario, método);' Es un trabajo en progreso, así que aún no sé si será posible. Pero es por eso que necesito analizar el parámetro genérico y verificar qué tipo de delegado se espera. –

+1

@Ritch: me recuerda haber comprobado el tipo de navegador en javascript en lugar de chequeo de funciones: el último es mucho más limpio. Tal vez injustificado en este caso, pero no tocaría el nombre si no fuera absolutamente necesario. – BrokenGlass

2

Esto parece funcionar:

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

Ejemplo:

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

único y dueces son ciertas. func es falso

+0

Pensé en verificar el nombre antes, pero esperaba que hubiera una solución más limpia/más segura. –

+0

Sí, parecía obvio. Tenía curiosidad por eso y por eso lo escribí. No creo que haya nada seguro cuando estás buscando tipos independientes y tratándolos como equivalentes. –

2

Estos son tipos distintos con nada en común excepto su nombre. El único atajo semi-razonable que puedo pensar:

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

Desde luego, no a prueba de fallos, pero quien declara sus propios tipos en el espacio de nombres System merece algo de dolor y sufrimiento.

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 para el árbol de Navidad :) Pero en este caso pruebe con un 'HashSet <>' .. – nawfal

+1

Técnicamente el código debería ser Array.IndexOf (_actionTypes, d.GetType(). GetGenericTypeDefinition())! = - 1. –

Cuestiones relacionadas