Created
July 25, 2014 06:59
-
-
Save benfoster/b1ff99336d7613dc5f81 to your computer and use it in GitHub Desktop.
Yet Another Bus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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