2011-06-24 18 views
16

Tengo una cantidad de 'trabajos' en mi aplicación, donde cada trabajo tiene una lista de métodos a los que necesita llamar, junto con sus parámetros. En esencia, una lista que contiene el siguiente objeto se llama:Métodos de llamada usando nombres en C#

string Name; 
List<object> Parameters; 

Así que, básicamente, cuando un trabajo se ejecuta quiero enumerar a través de esta lista, y llamar a sus métodos. Por ejemplo, si tengo un método como el siguiente:

TestMethod(string param1, int param2) 

Mi método objeto sería así:

Name = TestMethod 
Parameters = "astring", 3 

¿Es posible hacer esto? Me imagino que la reflexión será la clave aquí.

Respuesta

35

Sin duda, puede hacerlo de esta manera:

public class Test 
{ 
    public void Hello(string s) { Console.WriteLine("hello " + s); } 
} 

... 

{ 
    Test t = new Test(); 
    typeof(Test).GetMethod("Hello").Invoke(t, new[] { "world" }); 

    // alternative if you don't know the type of the object: 
    t.GetType().GetMethod("Hello").Invoke(t, new[] { "world" }); 
} 

El segundo parámetro de Invoke() es un conjunto de objetos que contiene todos los parámetros a pasar a su método.

Suponiendo que los métodos de todos pertenecen a la misma clase, que podría tener un método de esa clase algo como:

public void InvokeMethod(string methodName, List<object> args) 
{ 
    GetType().GetMethod(methodName).Invoke(this, args.ToArray()); 
} 
+0

Fantástico, exactamente lo que estoy buscando. Gracias :) – Chris

1

Si está utilizando .NET Framework 4, mira dynamic, de lo contrario GetMethod y luego llamar a Invoke de MethodInfo.

+0

No estoy triste, estoy en 3.5 – Chris

-1

Si está teniendo que recurrir a la reflexión, es probable que haya una mejor manera de llevar a cabo su tarea. Puede tomar un poco más de arquitectura, pero es factible.

Recuerde, tener más código no es algo malo, especialmente cuando complementa la legibilidad y la capacidad de administración de su código. La reflexión es difícil de entender para la mayoría, y usted pierde la mayor parte de su seguridad de tipo de tiempo de compilación. En su ejemplo, probablemente podría salirse con una declaración de cambio y objetos distintos para cada método que planeaba llamar. p.ej.

// Have some object hold the type of method it plans on calling. 
enum methodNames 
{ 
    Method1, 
    Method2 
} 

... 
class someObject 
{ 
    internal methodNames methodName {get; set;} 
    internal object[] myParams; 
} 
... 

// Execute your object based on the enumeration value it references. 
switch(someObject1.methodName) 
{ 
    case Method1: 
     Test.Method1(Int32.Parse(someObject1.myParams[0].ToString),someObject1.myParams[1].ToString()); 
     break; 
    ... 
} 

Si sabe que sólo tiene un conjunto distinto de posibilidades método a llamar, ¿por qué no se comprometa con anticipación?

1

NuGet to the rescue! PM> Install-Package dnpextensions

Una vez que tenga ese paquete en su proyecto, todos los objetos deberían tener ahora una extensión .InvokeMethod(), que tomará el nombre del método como una cadena y cualquier cantidad de parámetros.

Eso no utilizar técnicamente "cuerdas mágicas" para los nombres de los métodos, así que si quería a escribir su diccionario fuertemente método, usted podría hacer las llaves del tipo MethodInfo y obtener como esto ...

MethodInfo[] methodInfos = typeof(MyClass).GetMethods(); 

Y entonces usted puede hacer algo como esto ...

var methods = new Dictionary<MethodInfo, Object[]>(); 
foreach (var item in methods) 
    item.key.Invoke(null, item.value); 
    // 'null' may need to be an instance of the object that 
    // you are calling methods on if these are not static methods. 

O usted podría hacer alguna variación del bloque anterior utilizando los dnpextensions que he mencionado antes.

Cuestiones relacionadas