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?


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

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

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

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.


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


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

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.

15
esto no es de cuerdas!
— nawfal
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.