EventDelegator.cs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System;
  2. using System.Threading;
  3. namespace NetMQ
  4. {
  5. /// <summary>
  6. /// Facilitates a pattern whereby an event may be decorated with logic that transforms its arguments.
  7. /// </summary>
  8. /// <remarks>
  9. /// Use of this class requires providing actions that register and unregister a handler of the source
  10. /// event that calls <see cref="Fire"/> with updated arguments in response.
  11. /// </remarks>
  12. /// <typeparam name="T">Argument type of the decorated event.</typeparam>
  13. internal class EventDelegator<T> : IDisposable where T : EventArgs
  14. {
  15. private readonly Action m_registerToEvent;
  16. private readonly Action m_unregisterFromEvent;
  17. private EventHandler<T>? m_event;
  18. private int m_counter;
  19. /// <summary>
  20. /// Initialises a new instance.
  21. /// </summary>
  22. /// <param name="registerToEvent">an Action to perform when the first handler is registered for the event</param>
  23. /// <param name="unregisterFromEvent">an Action to perform when the last handler is unregistered from the event</param>
  24. public EventDelegator(Action registerToEvent, Action unregisterFromEvent)
  25. {
  26. m_registerToEvent = registerToEvent;
  27. m_unregisterFromEvent = unregisterFromEvent;
  28. }
  29. public event EventHandler<T> Event
  30. {
  31. add
  32. {
  33. m_event += value;
  34. if (Interlocked.Increment(ref m_counter) == 1)
  35. m_registerToEvent();
  36. }
  37. remove
  38. {
  39. m_event -= value;
  40. if (Interlocked.Decrement(ref m_counter) == 0)
  41. m_unregisterFromEvent();
  42. }
  43. }
  44. /// <summary>
  45. /// Raise, or "Fire", the Event.
  46. /// </summary>
  47. /// <param name="sender">the sender that the event-handler that gets notified of this event will receive</param>
  48. /// <param name="args">the subclass of EventArgs that the event-handler will receive</param>
  49. public void Fire(object sender, T args)
  50. {
  51. m_event?.Invoke(sender, args);
  52. }
  53. public void Dispose()
  54. {
  55. if (m_counter != 0)
  56. {
  57. m_unregisterFromEvent();
  58. m_counter = 0;
  59. }
  60. }
  61. }
  62. }