Обработка событий C#/Регистрация обратного вызова

События могут возвращать только void и получать объект sender/eventargs, верно?

Если это так, то craptastic.... как я могу передать указатель функции на другой объект, например:

public bool ACallBackFunc(int n) 
{
    return n > 0;
}

public void RegisterCallback(Something s)
{
     s.GiveCallBack(this.ACallBackFunc);
}

Something::GiveCallBack(Action? funcPtr)

Я пытался использовать Action, но мне нужно, чтобы он возвращал какое-то значение, а Actions может возвращать только void. Кроме того, мы не знаем, какой обратный вызов мы получим; он может возвращать что угодно и иметь любые параметры! Я думаю, что рефлексию придется как-то использовать.


person Jeff Dahmer    schedule 01.04.2010    source источник


Ответы (4)


вам нужно создать делегата, который передает обратно интересующие вас классы

открытый делегат недействителен CallbackDelegate (что-то); публичное событие CallbackDelegate myCallback

public void myFunction() { if (myCallback!= null) myCallback(new something()); }

ознакомьтесь с руководством по msdn... http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx

person yamspog    schedule 01.04.2010

Я написал события, которые возвращают значение, обычно bool. Однако использование функции Func позволяет возвращать значения.

person IAbstract    schedule 01.04.2010
comment
Пример прояснил бы ваш смысл. - person Robert Harvey; 01.04.2010
comment
Func‹› Кажется, мне нужно заранее знать возвращаемый тип... мы могли регистрировать неизвестный тип возвращаемого значения функции. - person Jeff Dahmer; 01.04.2010
comment
Попробуйте Func<object[], object>. Это получает любое количество аргументов любого типа (через массив объектов, например, при использовании ключевого слова params) и возвращает аргумент любого типа. - person Allon Guralnek; 26.04.2010

Действие по определению не возвращает значение, вы можете использовать общую версию, которая допускает несколько параметров.

Если вы хотите, чтобы он возвращал значение, используйте Func или, если вы просто хотите, чтобы он возвращал логическое значение и принимал один аргумент, вы можете использовать Predicate

Или вы можете определить делегата так, как хотите, чтобы он возвращал void или значение и принимал любое количество аргументов. Вы можете определить делегата, как показано ниже, и это похоже на тип, который вы можете использовать. Затем вы можете передать его как параметр обратного вызова напрямую, без использования Action, Func или Predicate. Пользовательский делегат также часто используется при написании пользовательского обработчика событий многоадресной рассылки.

public delegate double PerformAverageEventHandler(int val1, int val2, int val3);
person Fadrian Sudaman    schedule 01.04.2010

Возможно, вы не понимаете, что событие является многоадресным делегатом, позволяющим нескольким слушателям события. Это оставит вас (потенциально) с необходимостью получать более одного возвращаемого значения.

Некоторые идеи, чтобы обойти это, состоят в том, чтобы передать ссылочный объект обработчику событий, сохраняющему ссылку на объект. Вы могли бы получить результат, но вам потребуется другое событие, чтобы узнать, когда объект был изменен. Но, вероятно, было бы лучше переосмыслить то, чего вы пытаетесь достичь. Это звучит как рецепт переполнения стека, когда вы попадаете в бесконечный цикл события, вызывающего изменение, которое затем вызывает событие.

person Kirk    schedule 09.04.2010