Wywołanie funkcji z ciągu w C #


145

Wiem, że w php możesz wykonać połączenie takie jak:

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

function hello() { echo 'hello'; }

Czy to możliwe w .Net?


2
Widziałem, że twoja metoda też powinna być public.
zapoo

Odpowiedzi:


268

Tak. Możesz użyć refleksji. Coś takiego:

Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(TheCommandString);
theMethod.Invoke(this, userParameters);

56
A to wymaga "używania System.Reflection;"
jptsetung,

1
Czy można tego również użyć do wywołania funkcji z parametrem: np. String f = "metoda (parametr1, parametr2)";
Thunder

Dzięki @ottobar za odpowiedź. Nie wiem, czy właśnie tego szukam: potrzebowałem użyć funkcji skalarnej SQL w moim kodzie C #. Jak mam to nazwać?
Chagbert,

1
FYI, to nie działa, jeśli masz przeciążone metody.
Sean O'Neil,

Przy powyższym kodzie - wywoływana metoda musi mieć modyfikator dostępu - PUBLIC. Jeśli niepubliczne, użyj flag Binding - BindingFlags.NonPublic | Type thisType = this.GetType(); MethodInfo theMethod = thisType.GetMethod(TheCommandString, BindingFlags.NonPublic | BindingFlags.Instance); theMethod.Invoke(this, userParameters);
BindingFlags.Instance

75

Możesz wywołać metody instancji klasy za pomocą odbicia, wykonując dynamiczne wywołanie metody:

Załóżmy, że masz metodę o nazwie hello w rzeczywistym wystąpieniu (this):

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
a co z metodami z klasy „string”? używając frameworka 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();
        }
    }

to jest niezależne od klasy
Leandro

A metoda jest pusta?
Kiquenet

2

Nieznaczna styczna - jeśli chcesz przeanalizować i ocenić cały ciąg wyrażenia, który zawiera (zagnieżdżone!) Funkcje, rozważ NCalc ( http://ncalc.codeplex.com/ i nuget )

Dawny. nieznacznie zmodyfikowany w stosunku do dokumentacji projektowej:

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

A w ramach EvaluateFunctiondelegata nazwałbyś swoją istniejącą funkcję.


0

W rzeczywistości pracuję nad Windows Workflow 4.5 i muszę znaleźć sposób na przekazanie delegata z maszyny stanu do metody bez powodzenia. Jedynym sposobem, w jaki mogłem znaleźć, było przekazanie ciągu z nazwą metody, którą chciałem przekazać jako delegata, i przekonwertowanie ciągu na delegata wewnątrz metody. Bardzo ładna odpowiedź. Dzięki. Sprawdź ten link https://msdn.microsoft.com/en-us/library/53cz7sc6(v=vs.110).aspx


0
Ten kod działa w mojej aplikacji konsoli .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();
    }
}

Witamy w SO! Podoba mi się twoja odpowiedź, czy mógłbyś wyjaśnić trochę więcej o tym, co robisz?
a.deshpande012

Cześć, oczywiście. To jest konsolowa aplikacja .net, wewnątrz „klasy programu” znajduje się kilka metod lub funkcji, na przykład: hello, hello2, hello2. Metoda „CallMethod (metoda łańcuchowa)” wyszukuje i pozwala mi wywołać dowolną metodę wewnątrz „klasy programu” wywołaną przez nią jako parametr łańcuchowy. Kiedy uruchamiam aplikację z "konsoli Windows": piszę: "nazwa aplikacji" + "metoda, której potrzebuję wywołać". Na przykład: myapp witaj, a następnie zwróć „witaj świecie!”. Może to być również „myapp hello2” lub „myapp hello3”. Myślę, że mógłby pracować w dowolnej aplikacji .Net.
ranobe

Musisz dodać klasę Reflection: "using System.Reflection;".
ranobe

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.