Подписаться / отписаться (добавить / удалить) к событию внутри метода расширения
Я хочу создать свободный метод расширения для подписки на событие (и, что не менее важно, отписаться от него). Это расширение с использованием .RespondBy(Method)
вместо += new Eventhandler(Method)
Я хочу сделать это: object.WhenSomethingChanges.RespondBy(DoingThisOtherThing);
Вместо этого: object.WhenSomethingChanges += new EventHandler(DoingThisOtherThing);
Я занимался поиском в Google, и хотя я не совсем понял сложные детали, теперь я понимаю, что это связано с тем, обращаетесь ли вы к локальному полю или к публичному мероприятию.
С учетом сказанного, меня просто интересует, "как" это можно сделать, а не то, "почему" моя первая попытка не сработала. В противном случае обходной путь, по крайней мере, однозначное "Вы не можете сделать это... вообще никогда", также будет полезной информацией...
CommuncationsStatusPresenter (изображение)
CommuncationsStatusPresenter (Код)
using System;
using InspectionStation.Models;
using InspectionStation.Views;
using MachineControl.OPC;
namespace InspectionStation.Presenters
{
public class CommuncationsStatusPresenter
{
// Fields
private ICommunicationsModel m_model;
private ICommunicationsView m_view;
// Constructor
public CommuncationsStatusPresenter
(ICommunicationsModel p_model, ICommunicationsView p_view)
{
m_model = p_model;
m_view = p_view;
HookEvents();
}
private void HookEvents()
{
m_model
.When_Communications_Pulses_Heartbeat
.RespondBy(Setting_the_state_of_an_Indicator);
}
// Eventhandler
void Setting_the_state_of_an_Indicator(Tag sender, EventArgs e)
{
bool State = sender.BooleanValue;
m_view.Set_Communications_Status_Indicator = State;
}
}
}
RespondBy
using System;
namespace Common.Extensions
{
public static partial class ExtensionMethods
{
public static
void RespondBy<TSender, TEventArgs>(this
GenericEventHandler<TSender, TEventArgs> p_event,
GenericEventHandler<TSender, TEventArgs> p_handler
) where TEventArgs : EventArgs
{
p_event += new GenericEventHandler<TSender, TEventArgs>(p_handler);
}
}
}
using System;
namespace Common
{
[SerializableAttribute]
public delegate void GenericEventHandler<TSender, TEventArgs>
(TSender sender, TEventArgs e)
where TEventArgs : EventArgs;
}
ICommunicationsModel
using System;
using Common;
using MachineControl.OPC;
namespace InspectionStation.Models
{
public interface ICommunicationsModel
{
event GenericEventHandler<Tag, EventArgs>
When_Communications_Pulses_Heartbeat;
}
}
ICommunicationsView
namespace InspectionStation.Views
{
public interface ICommunicationsView
{
bool Set_Communications_Status_Indicator { set; }
}
}
2 ответа
Поскольку компилятор C# строго требует, чтобы за событиями, используемыми вне класса, следовал +=
или же -=
, команды присоединения и отсоединения для обработчиков, будет невозможно расширить и использовать это за пределами класса.
Однако, если вы хотите создать более конкретные методы для самого класса, например:
object.RespondWhenSomethingChangesBy(DoingThisOtherThing);
тогда внутри этого метода вы можете использовать метод расширения, потому что этот класс определил событие. Я знаю, это означает, что вы будете создавать много кода для событий, но если это то, что вы действительно хотите, то вышеупомянутое может оказаться еще более упорядоченным, чем:
object.WhenSomethingChanges.RespondBy(DoingThisOtherThing);
Я полностью понимаю вашу позицию здесь и надеюсь, что Microsoft решит, что события будут расширяться в будущем (я могу подумать о некоторых интересных причинах, по которым я буду ее использовать), но до тех пор, я думаю, нам просто придется обойти это. Это. Честно говоря, я уверен, что есть несколько очень веских причин, по которым он не был реализован в первую очередь, Microsoft довольно хорошо продумывает эти вещи.
Учитывая ответ Mike Perrenoud, я решил сделать следующее как часть моей схемы...
public class CommuncationsStatusPresenter
{
...
private void HookEvents()
{
m_model.
When_Communications_Pulses_Heartbeat += new EventHandler<Tag, EventArgs>(
Set_the_state_of_an_Indicator);
}
// Eventhandler
void Set_the_state_of_an_Indicator(Tag sender, EventArgs e)
{
...
}
}
}
В этом нет ничего особенного... просто согласованное автоматическое форматирование, основанное на новых строках, но, кажется, лучшее решение на данный момент (то есть. Я могу почти прочитать код вслух, чтобы быстро определить его намерения, не прибегая к обширным закомментированным описаниям).
Примечание: я переименовал длинный GenericEventHandler
просто EventHandler
так как особого имени не нужно.