2009-04-23 21 views
8

Supongamos que me dan un objeto y una cadena que contiene un nombre de método, ¿cómo puedo volver a un delegado para ese método (de ese método?)?C#: Devolver un delegado dado un objeto y un nombre de método

Ejemplo:

MyDelegate GetByName(ISomeObject obj, string methodName) 
{ 
    ... 
    return new MyDelegate(...); 
} 

ISomeObject someObject = ...; 
MyDelegate myDelegate = GetByName(someObject, "ToString"); 

//myDelegate would be someObject.ToString 

Gracias de antemano.

Una cosa más - que realmente no quieren utilizar una sentencia switch a pesar de que iba a funcionar, pero ser una tonelada de código.

Respuesta

20

Necesitará usar Type.GetMethod para obtener el método correcto, y Delegate.CreateDelegate para convertir el MethodInfo en un delegado. Ejemplo completo:

using System; 
using System.Reflection; 

delegate string MyDelegate(); 

public class Dummy 
{ 
    public override string ToString() 
    { 
     return "Hi there"; 
    } 
} 

public class Test 
{ 
    static MyDelegate GetByName(object target, string methodName) 
    { 
     MethodInfo method = target.GetType() 
      .GetMethod(methodName, 
         BindingFlags.Public 
         | BindingFlags.Instance 
         | BindingFlags.FlattenHierarchy); 

     // Insert appropriate check for method == null here 

     return (MyDelegate) Delegate.CreateDelegate 
      (typeof(MyDelegate), target, method); 
    } 

    static void Main() 
    { 
     Dummy dummy = new Dummy(); 
     MyDelegate del = GetByName(dummy, "ToString"); 

     Console.WriteLine(del()); 
    } 
} 

comentario de Mehrdad es un gran día, aunque - si las excepciones lanzadas por esta sobrecarga de Delegate.CreateDelegate están bien, puede simplificar GetByName significativamente:

static MyDelegate GetByName(object target, string methodName) 
    { 
     return (MyDelegate) Delegate.CreateDelegate 
      (typeof(MyDelegate), target, methodName); 
    } 

nunca he utilizado yo mismo , debido a que normalmente hago otros bits de comprobación después de encontrar el MethodInfo explícitamente - pero donde es adecuado, esto es muy útil :)

+5

'retorno (MyDelegate) Delegate.CreateDelegate (typeof (MyDelegate), objetivo, methodName);' no lo haría? –

+0

Lo haría, a menos que esté usando XNA o Compact Framework. Entonces, la solución de Jon debe ser utilizada. –

+1

Guau, en efecto, siempre que no se necesite una verificación de errores. Editaré ... –

3
static MyDelegate GetByName(object obj, string methodName) 
{ 
    return() => obj.GetType().InvokeMember(methodName, 
     System.Reflection.BindingFlags.InvokeMethod, null, obj, null); 
} 
+1

Si el método es incorrecto, que sólo fallará cuando intenta invocar al delegado, que generalmente no es tan útil como detectar el problema antes de tiempo. –

+1

Sí, hace bien el trabajo, y en algunas circunstancias, esto incluso podría ser deseable. –

+0

Suponiendo que el método no tiene parámetros, y si tiene que llamar más de una vez no le importa la sobrecarga – JoshBerke

1

Aún más fácil es utilizar:

public static MyDelegate GetByName(object target, string methodName) 
    { 
     return (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), 
       target, methodName); 
    } 

en cuenta que CreateDelegate tiene una sobrecarga que toma la methodName para usted. Esto se hizo con .NET 3.5 SP1

+0

La página de MSDN sugiere que ha estado en desde .NET 1.0 ... http://msdn.microsoft.com /en-us/library/12f294ye.aspx –

+0

Sí he estado leyendo esa página y debe ser sólo un poco confundido por la redacción de la nota en la página. – JoshBerke

+0

Creo que el 3.5 bit solo se trata de usar métodos no públicos. –

Cuestiones relacionadas