Invocando dinámicamente cualquier función pasando el nombre de la función como una cadena

StackOverflow https://stackoverflow.com/questions/801070

Pregunta

¿Cómo automatizo el proceso de creación de una instancia y su función se ejecuta de forma dinámica?

Gracias

Editar: Necesito una opción para pasar parámetros también. Gracias

¿Fue útil?

Solución

¿Quieres llamar a un constructor sin parámetros para crear la instancia? ¿También se especifica el tipo como una cadena, o se puede convertir en 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);
}

Otros consejos

Para invocar un constructor, Activator.CreateInstance Hará el truco. Tiene un montón de sobrecargas para hacer tu vida más fácil.

Si su constructor es sin parámetros :

object instance = Activator.CreateInstance(type)

Si necesita parámetros :

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

Para invocar, un método, una vez que tenga el Type objeto al que puede llamar GetMethod para obtener el método , 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 nula si es un método nulo),

Para 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;
        }
    }
}

Suponiendo que el método que desea invocar no tiene 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);
}

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

Supuesto: tienes 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 });  
    } 

hazme saber si mis suposiciones son incorrectas.

Pasar los parámetros dinámicamente. Aquí he tomado params string [] args, porque diferentes funciones tienen diferentes números de parámetros.

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

    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top