Skip to content

Instantly share code, notes, and snippets.

@noseratio
Last active July 16, 2021 12:10
Show Gist options
  • Save noseratio/d25371c91656e2d1c05e97700cc0fd98 to your computer and use it in GitHub Desktop.
Save noseratio/d25371c91656e2d1c05e97700cc0fd98 to your computer and use it in GitHub Desktop.
Simple pub/sub event hub implementation
#nullable enable
using System;
namespace conapp
{
/// <summary>
/// Resembling JavaScript's EventTarget
/// </summary>
public class EventTarget<T> where T : EventArgs
{
public event EventHandler<T>? Event;
public void Dispatch(object? source, T eventArgs) =>
this.Event?.Invoke(source, eventArgs);
}
/// <summary>
/// Emdbedding EventTarget into a container class as a property
/// </summary>
public interface IEventTargetProp<T> where T : EventArgs
{
public EventTarget<T> Value { get; init; }
}
/// <summary>
/// Implemented by EventTarget container class
/// </summary>
public interface IEventTargetHub
{
public EventTarget<T>? GetEventTarget<T>()
where T : EventArgs =>
(this as IEventTargetProp<T>)?.Value;
}
/// <summary>
/// Access EventTarget events on a container class using IEventTargetHub
/// </summary>
public static class EventTargetHubExtensions
{
public static bool HasEventTarget<T>(this IEventTargetHub @this)
where T : EventArgs =>
@this.GetEventTarget<T>() != null;
public static void AddListener<T>(this IEventTargetHub @this, EventHandler<T> listener)
where T : EventArgs =>
@this.GetEventTarget<T>()!.Event += listener;
public static void RemoveListener<T>(this IEventTargetHub @this, EventHandler<T> listener)
where T : EventArgs =>
@this.GetEventTarget<T>()!.Event -= listener;
public static void Dispatch<T>(this IEventTargetHub @this, object? source, T eventArgs)
where T : EventArgs =>
@this.GetEventTarget<T>()?.Dispatch(source, eventArgs);
}
// define some event signatures
class MyEventArgs : EventArgs { }
class YourEventArgs : EventArgs { }
class TheirEventArgs : EventArgs { }
// event container (hub)
class EventHub :
IEventTargetHub,
IEventTargetProp<MyEventArgs>,
IEventTargetProp<YourEventArgs>,
IEventTargetProp<TheirEventArgs>
{
EventTarget<MyEventArgs> IEventTargetProp<MyEventArgs>.Value { get; init; } = new();
EventTarget<YourEventArgs> IEventTargetProp<YourEventArgs>.Value { get; init; } = new();
EventTarget<TheirEventArgs> IEventTargetProp<TheirEventArgs>.Value { get; init; } = new();
}
// event listener
class Listener
{
public Listener(IEventTargetHub hub)
{
hub.GetEventTarget<MyEventArgs>()!.Event += Listener_Event;
hub.GetEventTarget<YourEventArgs>()!.Event += Listener_Event;
hub.GetEventTarget<TheirEventArgs>()!.Event += Listener_Event;
}
private void Listener_Event(object? sender, EventArgs e) =>
Console.WriteLine($"Listened to: {e.GetType().Name}");
}
// dispatch some events
class Program
{
static void Main(string[] args)
{
var hub = new EventHub();
var listener = new Listener(hub);
hub.Dispatch(hub, new MyEventArgs());
hub.Dispatch(hub, new YourEventArgs());
hub.Dispatch(hub, new TheirEventArgs());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment