Llamar a una función desde una cadena en C #

145

Sé que en php puedes hacer una llamada como:

$function_name = 'hello';
$function_name();

function hello() { echo 'hello'; }

¿Es esto posible en .Net?

Jeremy Boyd
fuente
2
Vi que tu método publictambién debería serlo .
zapoo

Respuestas:

268

Si. Puedes usar la reflexión. Algo como esto:

Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(TheCommandString);
theMethod.Invoke(this, userParameters);
ottobar
fuente
56
Y esto requiere "usar System.Reflection;"
jptsetung
1
¿Podría esto también utilizarse para invocar una función con parámetro: por ejemplo, cadena f = "método (parámetro1, parámetro2)";
Trueno
Gracias @ottobar por la respuesta. No sé si esto es lo que también estoy buscando: necesitaba usar una función escalar SQL en mi código C #. ¿Cómo lo llamo?
Chagbert
1
Para su información, esto no funciona si ha sobrecargado los métodos.
Sean O'Neil
Con el código anterior - El método que se invoca debe tener un modificador de acceso - PUBLIC. Si no es público, utilice indicadores de enlace - BindingFlags.NonPublic | BindingFlags.Instance .. Type thisType = this.GetType(); MethodInfo theMethod = thisType.GetMethod(TheCommandString, BindingFlags.NonPublic | BindingFlags.Instance); theMethod.Invoke(this, userParameters);
Sibgath
75

Puede invocar métodos de una instancia de clase utilizando la reflexión, haciendo una invocación de método dinámico:

Suponga que tiene un método llamado hello en la instancia real (esto):

string methodName = "hello";

//Get the method information using the method info class
 MethodInfo mi = this.GetType().GetMethod(methodName);

//Invoke the method
// (null- no parameter for the method call
// or you can pass the array of parameters...)
mi.Invoke(this, null);
CMS
fuente
1
¿Qué pasa con los métodos de una clase "string"? usando el marco 4
Leandro
36
class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyReflectionClass);
            MethodInfo method = type.GetMethod("MyMethod");
            MyReflectionClass c = new MyReflectionClass();
            string result = (string)method.Invoke(c, null);
            Console.WriteLine(result);

        }
    }

    public class MyReflectionClass
    {
        public string MyMethod()
        {
            return DateTime.Now.ToString();
        }
    }
BFree
fuente
esto no depende de la clase
Leandro
¿Y el método vacío?
Kiquenet
2

Una ligera tangente: si desea analizar y evaluar una cadena de expresión completa que contiene funciones (anidadas), considere NCalc ( http://ncalc.codeplex.com/ y nuget)

Ex. ligeramente modificado de la documentación del proyecto:

// the expression to evaluate, e.g. from user input (like a calculator program, hint hint college students)
var exprStr = "10 + MyFunction(3, 6)";
Expression e = new Expression(exprString);

// tell it how to handle your custom function
e.EvaluateFunction += delegate(string name, FunctionArgs args) {
        if (name == "MyFunction")
            args.Result = (int)args.Parameters[0].Evaluate() + (int)args.Parameters[1].Evaluate();
    };

// confirm it worked
Debug.Assert(19 == e.Evaluate());

Y dentro del EvaluateFunctiondelegado llamaría a su función existente.

drzaus
fuente
0

De hecho, estoy trabajando en Windows Workflow 4.5 y encontré una manera de pasar un delegado de una máquina de estado a un método sin éxito. La única forma en que pude encontrar fue pasar una cadena con el nombre del método que quería pasar como delegado y convertir la cadena en un delegado dentro del método. Muy buena respuesta. Gracias. Consulte este enlace https://msdn.microsoft.com/en-us/library/53cz7sc6(v=vs.110).aspx

Antonio Leite
fuente
0
Este código funciona en mi aplicación de consola .Net
class Program
{
    static void Main(string[] args)
    {
        string method = args[0]; // get name method
        CallMethod(method);
    }
    
    public static void CallMethod(string method)
    {
        try
        {
            Type type = typeof(Program);
            MethodInfo methodInfo = type.GetMethod(method);
            methodInfo.Invoke(method, null);
        }
        catch(Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
            Console.ReadKey();
        }
    }
    
    public static void Hello()
    {
        string a = "hello world!";
        Console.WriteLine(a);
        Console.ReadKey();
    }
}
ranobe
fuente
Bienvenido a SO! Me gusta tu respuesta, ¿podrías explicarme un poco más sobre lo que estás haciendo?
a.deshpande012
Hola, por supuesto. Esta es una aplicación .net de consola, dentro de la "clase de programa" hay varios métodos o funciones, por ejemplo: hello, hello2, hello2. El método "CallMethod (método de cadena)" busca y me permite invocar cualquier método dentro de la "clase de programa" invocado por su nombre como parámetro de cadena. Cuando ejecuto la aplicación desde "Consola de Windows": escribo: "nombre de la aplicación" + "método que necesito invocar". Por ejemplo: myapp hello, luego devuelve "hello world!". También podría ser "myapp hello2" o "myapp hello3". Creo que podría funcionar en cualquier aplicación .Net.
Ranobe
Debe agregar la clase Reflection: "using System.Reflection;".
Ranobe
-9

En C #, puede crear delegados como punteros de función. Consulte el siguiente artículo de MSDN para obtener información sobre el uso:http://msdn.microsoft.com/en-us/library/ms173171(VS.80).aspx

    public static void hello()
    {
        Console.Write("hello world");
    }

   /* code snipped */

    public delegate void functionPointer();

    functionPointer foo = hello;
    foo();  // Writes hello world to the console.
regex
fuente
15
esto no es de cuerdas!
nawfal