Как передать функцию в качестве параметра в C#?
можно ли передать функцию в качестве параметра в C#? Я могу сделать это с помощью классов Func или Action, но это заставляет меня объявлять всю сигнатуру функции сразу. Когда я пытаюсь использовать делегат, я получаю ошибку компиляции, говоря, что он не может преобразовать группу методов в делегат.
Я работаю над Аксиальные и я пытаюсь разрешить пользователям вызывать веб-службы. То, что я собираюсь сделать, - это возможность создать прокси-класс Visual Studio, а затем передать сгенерированный функция. Сигнатура функции не имеет значения, потому что сгенерированный код использует только имя функции. Однако я хотел бы передать функцию вместо имени по двум причинам: возможность использовать свойство Url прокси и ошибку компилятора, если веб-служба не существует или обновляется в Visual Studio.
public void AlertIt(object o) {
Axial.DOM.Window.Alert(o.ToString());
}
public void CallAddService() {
object[] param = new object[] { int.Parse(txtA.Text), int.Parse(txtB.Text) };
Axial.ServerScript.CallWebService(new WSProxy.WS().Add, param, AlertIt, AlertIt);
}
class Axial.ServerScript {
public void CallWebService(Delegate method, object[] param, Action<object> successCallback, Action<object> failureCallback) {
// translate to javascript (already working)
}
}
8 ответов:
Я думаю, что вы хотите:
static object InvokeMethod(Delegate method, params object[] args){ return method.DynamicInvoke(args); } static int Add(int a, int b){ return a + b; } static void Test(){ Console.WriteLine(InvokeMethod(new Func<int, int, int>(Add), 5, 4)); }печать "9".
преобразование группы методов, анонимного метода или лямбда-выражения в делегат требует, чтобы компилятор знал точный тип делегата. Однако вы можете потенциально использовать лямбда-выражения и захваченные переменные, чтобы сделать это проще:
public void InvokeMethod(Action action) { action(); } public int Add(int a, int b) { return a + b; } public void Test() { InvokeMethod(() => Add(2, 3)); }это в основном задерживает вызов обычным способом, но путем обертывания фактического вызова в
Addв простомActionделегат.если это не соответствует вашим требованиям, возможно, вы можете рассказать нам немного больше о то, что вы действительно пытаетесь достичь.
правка: если это сгенерированный код, вы можете привести к
Func<...>с правильными аргументами типа - если их не слишком много. Кроме этого, нет никакого реального способа просто передать группу методов. Там были случайные звонки для " infoof(...) "оператор (например, typeof, но для членов), который даст вам MemberInfo, но это на самом деле не существует.
сначала у вас должен быть делегат
delegate int Operation(int a, int b)затем он приобретает следующий вид:
public void InvokeMethod(Operation method, object target, object param) { method((int) target, (int) param); }нет необходимости для любого вызова для вызова.
как с бкость я не понимаю, зачем тебе параметры[] массив. Не могли бы Вы уточнить расширенное использование для параметров?
кроме того, мне придется исправить что-то в вашем вопросе, потому что это вызовет ошибку компиляции :p
пожалуйста, посмотрите на использование делегатов вот отличный пример
Почему вы используете отражение? будет ли когда-нибудь другое количество параметров? или вы знаете, что метод signture останется постоянным (также помните, что C# поддерживает ключевое слово params [])
HTH
кости
посмотреть Серия Функционального Программирования по Justin Etheredge. Вы должны найти решение своей проблемы там.
Это очень простой пример, для программиста, который уже знаком с (C / C++/VB.NET/Python) - style pass function by указатель / ref (С делегат C#):
delegate void CALLBACK(String s); static void Main(string[] args) { Get("some string", testfunc); Util.pause(); } static void Get(String s, CALLBACK x) { x(s); } static void testfunc(String s) { Console.WriteLine(s); }
скажем, если вам нужно передать метод в качестве параметра, а также вам нужно поймать возвращаемое значение для дальнейшей обработки . Тогда приведенные выше примеры будут работать нормально . Но скажем, если вам нужно передать метод с типом возврата void, вам нужно создать еще одну версию функции InvokeMethod. Проверьте пример ниже.
private static T retry<T>(Delegate method, params object[] args) { for (int i = 0; i <= 3; i++) { try { return (T)method.DynamicInvoke(args); } catch (Exception ex) { if (i == 3) { logMessage(ex.Message); } Console.WriteLine("Retry count " + i); Thread.Sleep(10); } } return default(T); } private static void retry2(Delegate method, params object[] args) { for (int i = 0; i <= 3; i++) { try { method.DynamicInvoke(args); break; } catch (Exception ex) { if (i == 3) { logMessage(ex.Message); //return default(T); } Console.WriteLine("Retry count " + i); Thread.Sleep(10); } } } static bool isSuccess = true; static void logMessage(string msg) { isSuccess = false; Console.WriteLine(msg); } static int Add(int a, int b) { return a + b; } static void Add2(int a, int b) { int c = a + b; Console.WriteLine(c); } static void Main(string[] args) { int d = retry<int>(new Func<int, int, int>(Add), 6, 7.7); Console.Write(" " + d + "\n"+isSuccess); retry2(new Action<int, int>(Add2), 45, 60); Console.ReadKey(); }
что-то вроде это должно работать для вас:
delegate int MyDelegate(int a, int b); public int Add(int a, int b) { return a + b; } public void InvokeMethod(Delegate method, object[] param) { Console.WriteLine(method.DynamicInvoke(param)); } public Form1() { InitializeComponent(); InvokeMethod(new MyDelegate(Add), new object[] { 1, 2 }); }удачи!
Comments