2009-08-18 7 views

Respuesta

11

sí se puede utilizar System.Reflection


CallStaticMethod("MainApplication.Test", "Test1"); 

public static void CallStaticMethod(string typeName, string methodName) 
{ 
    var type = Type.GetType(typeName); 

    if (type != null) 
    { 
     var method = type.GetMethod(methodName); 

     if (method != null) 
     { 
      method.Invoke(null, null); 
     } 
    } 
} 

public static class Test 
{ 
    public static void Test1() 
    { 
     Console.WriteLine("Test invoked"); 
    } 
} 
+0

Buen ejemplo; estaba a punto de publicar casi exactamente la mismo código (las únicas diferencias son que en mi versión CallStaticMethod toma solo una cadena y la corta internamente para separar el tipo del nombre del método, y también devuelve el resultado del método). –

1

Usted podría intentar algo como:

typeof (MyClass).GetMethod (MyClass.GetData) // Assuming get data is the string name. 

que volvería a que una clase MethodInfo. A partir de ahí, puede usar el método Invoke (con los parámetros correctos).

+2

Hay una serie de problemas con esta muestra, el principal es que no compilará, ya que GetMethod toma un argumento 'string'. También hay una llamada innecesaria a 'GetType'; 'typeof (MyClass)' devuelve un objeto 'Type'. Invocar 'GetType' en ese objeto devolverá el objeto' Type' que describe 'Type' en lugar de' MyClass', y no se encontrará el método 'GetData'. –

+0

la intención es correcta - el código no es – Gishu

+0

Disculpas, fue el resultado de la primera pasada cometida con la segunda ... mi compilador de C# incorporado falló (; – Kieron

1

La respuesta está en la reflexión. Puede usar la reflexión para obtener la MethodInfo de cierto tipo. (Debe saber el tipo que es), y luego puede invocarlo.

Pero, ¿está seguro de que no hay una solución mejor para resolver su problema? ¿Por qué se pasa como una cadena?

2

Sí Puede usar el método de reflexión para buscar el método e invocar con argumentos apropiados.

2

Reflection API

class Test 
{ 
    public void Print(int n) 
    { 
     Console.WriteLine(n); 
    } 
} 
class MainA 
{ 
    static void Main() 
    { 
     Type t = typeof(Test); 
     Object obj = new Test(); 
     System.Reflection.MethodInfo m = t.GetMethod("Print"); 
     m.Invoke(obj,new object[]{11}); 
    } 
} 
1

reflexión tiene las herramientas básicas que necesita, pero todavía tendrá que analizar la cadena de sí mismo (dividirlo en los puntos y lo refleja todo el camino hasta la MethodInfo necesaria). Sin embargo, debe tener en cuenta que el rendimiento de dicha operación es varios cientos (si no miles o más) veces más lento que la invocación directa del método. Está bien hacerlo un par de veces, pero si tiene la intención de hacer esto mucho, debería considerar refaccionar su código de tal manera que no sea necesario.

Si realmente no puede evitar esto (y en la mayoría de los casos puede), puede al menos acelerarlo almacenando en caché los objetos MethodInfo que haya encontrado en algún diccionario. De esta forma no tendrás que reflexionar siempre.

Además, en caso de que no las conozca, le aconsejo que busque delegates. Lo más probable es que esta sea una respuesta a su problema. Y es casi tan rápido como una llamada directa al método.

0

Sí. Lo único que debe hacer es proporcionar el espacio de nombres de la clase también.

Hath parece haberlo clavado. Desde que tomé la molestia de escribirlo fuera .. Aquí está mi versión (temp es el espacio de nombres, el usuario es el nombre de clase y que existe es un método estático público dentro de ella.)

private static object ExecuteStaticMethod(string method_full_path, object[] args) 
     { 
     var tokens = method_full_path.Split('.'); 
     string class_full_name = String.Format("{0}.{1}", tokens[0], tokens[1]); 
     var class_blueprint = Assembly.GetExecutingAssembly().GetType(class_full_name); 
     var handle_to_method = class_blueprint.GetMethod(tokens[2], BindingFlags.Default | BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public); 
     return handle_to_method.Invoke(null, args); 

     } 

     public static void Main(string[] args) 
     { 
     Console.WriteLine(ExecuteStaticMethod("temp.User.Exists", new object[] {"Gishu"})); // prints false 
     User.Create("Gishu"); 
     Console.WriteLine(ExecuteStaticMethod("temp.User.Exists", new object[] { "Gishu" })); // prints true 
     } 
1

Antes de ir por el camino de la reflexión, que es lo que se llama hacer, asegúrese de que no haya otra forma mejor de implementarlo. Primero compruebe los delegados, ya que pueden llamar a un método que está configurado en tiempo de ejecución.

Así que aquí van para la reflexión:

public void MyFunction() 
{ 
    string dotSeparatedParams = "Myclass.Method"; 
    string[] arrayParams = dotSeparatedParams.Split('.'); 
    // since the class was defined in the string, start with loading it 
    Type classType = Type.GetType(arrayParams[0]); 
    if(classType == null) 
     throw new Exception(); 
    // load the reference to the method 
    MethodInfo mi = classType.GetMethod(arrayParams[1]); 
    if (mi == null) 
     throw new Exception(); 
    // call the method 
    mi.Invoke(null, null); 
} 

Unas pocas notas:

  • En este ejemplo, el método debe ser estática. La razón es que no estamos instalando 'MyClass'. Es posible hacerlo, pero requiere un contructor predeterminado sin parámetros. Mira .GetConstructor para eso. Pero, en general, no es aconsejable crear la clase sobre la marcha para llamar a un método.
  • El método estático no toma ningún parámetro en mi ejemplo. Si lo hace, entonces reemplace el segundo argumento de mi.Invocar (...) con una matriz de objetos: nuevo objeto [2] {232, "una cadena"}
  • Puede pasar el objeto sobre el que desea llama el método en su lugar. Tendría un parámetro para MyFunction que toma un objeto de tipo 'MyClass' y pasaría ese objeto a la llamada mi.Invoke().
Cuestiones relacionadas