Created
March 5, 2012 16:39
-
-
Save jdaigle/1979180 to your computer and use it in GitHub Desktop.
This file contains hidden or 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; | |
namespace Clearwave.ServiceBus { | |
public class MessageHandlerCollection { | |
private readonly static Type messageHandlerOpenGenericType = typeof(IMessageHandler<>); | |
private IDictionary<Type, ISet<DispatchInfo>> messageHandlers = new Dictionary<Type, ISet<DispatchInfo>>(); | |
public static IList<Type> FindAllMessageTypes(IEnumerable<Assembly> messageHandlerAssemblies) { | |
// Get all types that are used to close the generic type IMessageHandler<> | |
var types = new List<Type>(); | |
foreach (var assembly in messageHandlerAssemblies) { | |
types.AddRange(assembly.GetTypes() | |
.WhereMessageHandlerType() | |
.SelectMany(x => x.GetInterfaces().Where(i => i.IsGenericType && | |
i.GetGenericTypeDefinition() == messageHandlerOpenGenericType) | |
.Select(i => i.GetGenericArguments().FirstOrDefault()))); | |
} | |
return types.Distinct().ToList(); | |
} | |
public static IList<Type> FindMessageHandlers(Type messageType, IEnumerable<Assembly> messageHandlerAssemblies) { | |
// Find every message handler type | |
var messageHandlerTypes = messageHandlerAssemblies | |
.SelectMany(a => a.GetTypes() | |
.WhereMessageHandlerType() | |
.Where(t => t.GetInterfaces().Any(i => i.IsGenericType && | |
i.GetGenericTypeDefinition() == messageHandlerOpenGenericType && | |
i.GetGenericArguments().FirstOrDefault().IsAssignableFrom(messageType)))); | |
return messageHandlerTypes.ToList(); | |
} | |
public void ExecuteTheseHandlersFirst(params Type[] handlerTypes) { | |
foreach (var messageType in messageHandlers.Keys.ToList()) { | |
var handlers = messageHandlers[messageType]; | |
var firstOrderedHandlers = new HashSet<DispatchInfo>(); | |
foreach (var handler in handlerTypes) { | |
var firstOrderedHandler = handlers.FirstOrDefault(x => handler.IsAssignableFrom(x.InstanceType)); | |
if (firstOrderedHandler != null && !firstOrderedHandlers.Contains(firstOrderedHandler)) { | |
firstOrderedHandlers.Add(firstOrderedHandler); | |
} | |
} | |
messageHandlers[messageType] = new HashSet<DispatchInfo>(firstOrderedHandlers.Concat(handlers.Except(firstOrderedHandlers))); | |
} | |
} | |
public void RegisterDispatchHandler(Type messageType, IEnumerable<Assembly> messageHandlerAssemblies) { | |
// Find every message handler type | |
var messageHandlerTypes = FindMessageHandlers(messageType, messageHandlerAssemblies); | |
// Add the dispatch info for each message handler | |
foreach (var instanceType in messageHandlerTypes) { | |
if (!messageHandlers.ContainsKey(messageType)) messageHandlers.Add(messageType, new HashSet<DispatchInfo>()); | |
foreach (var methodInfo in instanceType.GetMethods().Where(x => x.GetParameters().Count() == 1 && | |
x.GetParameters().Single().ParameterType.IsAssignableFrom(messageType))) { | |
if (messageHandlers[messageType].Any(x => x.MessageType == messageType && x.InstanceType == instanceType && x.MethodInfo == methodInfo)) continue; | |
messageHandlers[messageType].Add(new DispatchInfo(messageType, instanceType, methodInfo)); | |
} | |
} | |
} | |
public void RegisterDispatchHandler(IEnumerable<Type> messageTypes, IEnumerable<Assembly> messageHandlerAssemblies) { | |
foreach (var messageType in messageTypes) { | |
RegisterDispatchHandler(messageType, messageHandlerAssemblies); | |
} | |
} | |
public void RegisterDispatchHandler(IEnumerable<Assembly> messageHandlerAssemblies) { | |
RegisterDispatchHandler(FindAllMessageTypes(messageHandlerAssemblies), messageHandlerAssemblies); | |
} | |
public void RegisterDispatchHandler(params Assembly[] messageHandlerAssemblies) { | |
RegisterDispatchHandler((IEnumerable<Assembly>)messageHandlerAssemblies); | |
} | |
public void RegisterDispatchHandler(Assembly messageHandlerAssembly) { | |
RegisterDispatchHandler(new[] { messageHandlerAssembly }); | |
} | |
public IEnumerable<Type> AllTypes() { | |
return messageHandlers.Keys; | |
} | |
public IEnumerable<DispatchInfo> OrderedHandlersFor(Type messageType) { | |
if (messageHandlers.ContainsKey(messageType)) { | |
return messageHandlers[messageType]; | |
} else { | |
return new DispatchInfo[0]; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment