Skip to content

Instantly share code, notes, and snippets.

@benfoster
Created July 25, 2014 06:59
Show Gist options
  • Save benfoster/b1ff99336d7613dc5f81 to your computer and use it in GitHub Desktop.
Save benfoster/b1ff99336d7613dc5f81 to your computer and use it in GitHub Desktop.
Yet Another Bus
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ReflectionDemo
{
class Program
{
static void Main(string[] args)
{
var bus = new Bus();
bus.Receive<TestMessage>(msg =>
{
Console.WriteLine(msg.Text);
return Task.FromResult(0);
});
bus.RegisterReceiver(() => new TestMessageHandler());
bus.RegisterReceiver<TestMessageHandler, TestMessage>();
bus.RegisterReceiver(typeof(TestMessageHandler), type => Activator.CreateInstance(type));
bus.Send(new TestMessage { Text = "test" });
Console.ReadLine();
}
}
class TestMessage
{
public string Text { get; set; }
}
class Bus
{
private Dictionary<Type, ICollection<Func<object, Task>>> handlers =
new Dictionary<Type, ICollection<Func<object, Task>>>();
public void Send<TMessage>(TMessage message)
{
foreach (var handler in GetMessageHandlers<TMessage>())
{
handler.Invoke(message);
}
}
public void Receive<TMessage>(Func<TMessage, Task> handler)
{
var handlers = GetMessageHandlers<TMessage>();
handlers.Add(msg => handler((TMessage)msg));
}
private ICollection<Func<object, Task>> GetMessageHandlers<TMessage>()
{
ICollection<Func<object, Task>> msgHandlers = null;
if (!handlers.TryGetValue(typeof(TMessage), out msgHandlers))
{
msgHandlers = new List<Func<object, Task>>();
handlers[typeof(TMessage)] = msgHandlers;
}
return msgHandlers;
}
}
interface IReceive<TMessage>
{
Task Handle(TMessage message);
}
class TestMessageHandler : IReceive<TestMessage>
{
public Task Handle(TestMessage message)
{
Console.WriteLine("Test Message Handler: {0}", message.Text);
return Task.FromResult(0);
}
}
static class BusExtensions
{
public static void RegisterReceiver<TMessage>(this Bus bus, Func<IReceive<TMessage>> handlerFactory)
{
bus.Receive<TMessage>(handlerFactory().Handle);
}
public static void RegisterReceiver<THandler, TMessage>(this Bus bus) where THandler : IReceive<TMessage>
{
bus.RegisterReceiver<TMessage>(() => (THandler)Activator.CreateInstance<THandler>());
}
public static void RegisterReceiver(this Bus bus, Type receiverType, Func<Type, object> receiverFactory)
{
var messageType = receiverType.GetInterfaces().First().GetGenericArguments()[0];
var handleDelegateType = typeof(Func<,>).MakeGenericType(messageType, typeof(Task));
var handlerInstance = receiverFactory(receiverType); // shouldn't be created before
var handleDelegate = Delegate.CreateDelegate(handleDelegateType, handlerInstance, "Handle");
var receiveMethod = typeof(Bus).GetMethod("Receive").MakeGenericMethod(messageType);
receiveMethod.Invoke(bus, new[] { handleDelegate });
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment