2009-04-29 11 views

Respuesta

44

¿Desea simplemente llamar a un constructor sin parámetros para crear la instancia? ¿El tipo también se especifica como una cadena o puede hacerlo un método genérico? Por ejemplo:

// All error checking omitted. In particular, check the results 
// of Type.GetType, and make sure you call it with a fully qualified 
// type name, including the assembly if it's not in mscorlib or 
// the current assembly. The method has to be a public instance 
// method with no parameters. (Use BindingFlags with GetMethod 
// to change this.) 
public void Invoke(string typeName, string methodName) 
{ 
    Type type = Type.GetType(typeName); 
    object instance = Activator.CreateInstance(type); 
    MethodInfo method = type.GetMethod(methodName); 
    method.Invoke(instance, null); 
} 

o

public void Invoke<T>(string methodName) where T : new() 
{ 
    T instance = new T(); 
    MethodInfo method = typeof(T).GetMethod(methodName); 
    method.Invoke(instance, null); 
} 
7

Suponiendo que el método que desea invocar no toma ningún parámetro:

public void InvokeMethod(Type type, string methodName) 
{ 
    object instance = Activator.CreateInstance(type); 
    MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 

    method.Invoke(instance, null); 
} 
3

Creo que su problema es demasiado genérico aquí, estoy proporcionando una solución con ciertas suposiciones aquí.

Asunción: tiene un typeName (cadena), methodName (cadena) y un parámetro (de SomeType).

public static void InvokeMethod(string typeName, string methodName, SomeType objSomeType) { 
     Type type = Type.GetType(typeName); 
     if(type==null) { 
     return; 
     } 
     object instance = Activator.CreateInstance(type); //Type must have a parameter-less contructor, or no contructor. 
     MethodInfo methodInfo =type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public); 
     if(methodInfo==null) { 
     return; 
     } 
     methodInfo.Invoke(instance, new[] { objSomeType }); 
    } 

hágamelo saber si mis suposiciones son incorrectas.

16

Para invocar un constructor, Activator.CreateInstance hará el truco. Tiene un montón de sobrecargas para hacerte la vida más fácil.

Si su constructor es parameterless:

object instance = Activator.CreateInstance(type) 

Si necesita parameters:

object instance = Activator.CreateInstance(type, param1, param2) 

Invocar, un método, una vez que tenga el objeto Type puede llamar GetMethod para obtener el method, y luego Invoke (con o sin parámetros) para invocarlo. Si lo necesita, Invoke también le dará el valor de retorno de la función que está llamando (o nulo si es un método nulo),

Para obtener una muestra un poco más detallada (pegar en una aplicación de consola y listo):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Reflection; 

namespace Test 
{ 
    public static class Invoker 
    { 
     public static object CreateAndInvoke(string typeName, object[] constructorArgs, string methodName, object[] methodArgs) 
     { 
      Type type = Type.GetType(typeName); 
      object instance = Activator.CreateInstance(type, constructorArgs); 

      MethodInfo method = type.GetMethod(methodName); 
      return method.Invoke(instance, methodArgs); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Default constructor, void method 
      Invoker.CreateAndInvoke("Test.Tester", null, "TestMethod", null); 

      // Constructor that takes a parameter 
      Invoker.CreateAndInvoke("Test.Tester", new[] { "constructorParam" }, "TestMethodUsingValueFromConstructorAndArgs", new object[] { "moo", false }); 

      // Constructor that takes a parameter, invokes a method with a return value 
      string result = (string)Invoker.CreateAndInvoke("Test.Tester", new object[] { "constructorValue" }, "GetContstructorValue", null); 
      Console.WriteLine("Expect [constructorValue], got:" + result); 

      Console.ReadKey(true); 
     } 
    } 

    public class Tester 
    { 
     public string _testField; 

     public Tester() 
     { 
     } 

     public Tester(string arg) 
     { 
      _testField = arg; 
     } 

     public void TestMethod() 
     { 
      Console.WriteLine("Called TestMethod"); 
     } 

     public void TestMethodWithArg(string arg) 
     { 
      Console.WriteLine("Called TestMethodWithArg: " + arg); 
     } 

     public void TestMethodUsingValueFromConstructorAndArgs(string arg, bool arg2) 
     { 
      Console.WriteLine("Called TestMethodUsingValueFromConstructorAndArg " + arg + " " + arg2 + " " + _testField); 
     } 

     public string GetContstructorValue() 
     { 
      return _testField; 
     } 
    } 
} 
+1

Tnx mucho. Entre estas respuestas, solo esto funcionó para mí ... –

+0

¿Qué pasa si no hay espacio de nombres? ¿Cómo proporcionamos typeName – MonsterMMORPG

2

Para pasar los parámetros dinámicamente cadena params Aquí he tomado [] args, porque diferentes funciones tienen diferente número de parámetros de modo.

public void Invoke(string typeName,string functionName,params string[] args) 
    { 

    Type type = Type.GetType(typeName); 
    dynamic c=Activator.CreateInstance(type); 
    //args contains the parameters(only string type) 
    type.InvokeMember(functionName,BindingFlags.InvokeMethod,null,c,args); 

    } 
+2

Big +1 para el uso de InvokeMember para obtener el método correcto e invocar todo en uno? Si OP necesita MethodInfo, creo que hay reemplazos para GetMethod que de manera similar toman tipos de parámetros para obtener el mejor método. –

Cuestiones relacionadas