Invocando dinámicamente cualquier función pasando el nombre de la función como una cadena
-
03-07-2019 - |
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
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);
}