Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="cdmdotnet Limited">
4 : // // Copyright cdmdotnet Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Linq;
12 : using Cqrs.Commands;
13 : using Cqrs.Events;
14 : using Cqrs.Infrastructure;
15 : using Cqrs.Messages;
16 :
17 : namespace Cqrs.Bus
18 : {
19 : public class RouteManager
20 : : IHandlerRegistrar
21 0 : {
22 : protected IDictionary<Type, Route> Routes { get; private set; }
23 :
24 : private static Type CommandType { get; set; }
25 :
26 : private static Type EventType { get; set; }
27 :
28 0 : public RouteManager()
29 : {
30 : Routes = new Dictionary<Type, Route>();
31 : }
32 :
33 : static RouteManager()
34 : {
35 : CommandType = typeof (ICommand<>);
36 : EventType = typeof (IEvent<>);
37 : }
38 :
39 : #region Implementation of IHandlerRegistrar
40 :
41 : /// <summary>
42 : /// Register an event or command handler that will listen and respond to events or commands.
43 : /// </summary>
44 1 : public virtual void RegisterHandler<TMessage>(Action<TMessage> handler, Type targetedType, bool holdMessageLock = true)
45 : where TMessage : IMessage
46 : {
47 : Route route;
48 : if (!Routes.TryGetValue(typeof(TMessage), out route))
49 : {
50 : route = new Route
51 : {
52 : Handlers = new List<RouteHandlerDelegate>()
53 : };
54 : Routes.Add(typeof(TMessage), route);
55 : }
56 : route.Handlers.Add
57 : (
58 : new RouteHandlerDelegate
59 : {
60 : Delegate = DelegateAdjuster.CastArgument<IMessage, TMessage>(x => handler(x)),
61 : TargetedType = targetedType
62 : }
63 : );
64 : }
65 :
66 : /// <summary>
67 : /// Register an event or command handler that will listen and respond to events or commands.
68 : /// </summary>
69 1 : public void RegisterHandler<TMessage>(Action<TMessage> handler, bool holdMessageLock = true)
70 : where TMessage : IMessage
71 : {
72 : RegisterHandler(handler, null, holdMessageLock);
73 : }
74 :
75 : #endregion
76 :
77 0 : public RouteHandlerDelegate GetSingleHandler<TMessage>(bool throwExceptionOnNoRouteHandlers = true)
78 : where TMessage : IMessage
79 : {
80 : Route route;
81 : Type messageType = typeof(TMessage);
82 : bool isACommand = IsACommand(messageType);
83 :
84 : if (Routes.TryGetValue(typeof(TMessage), out route))
85 : {
86 : if (route.Handlers == null || route.Handlers.Count != 1)
87 : {
88 : if (isACommand)
89 : throw new MultipleCommandHandlersRegisteredException(messageType);
90 : throw new InvalidOperationException("Cannot send to more than one handler.");
91 : }
92 : return route.Handlers.Single();
93 : }
94 :
95 : if (throwExceptionOnNoRouteHandlers)
96 : {
97 : if (isACommand)
98 : throw new NoCommandHandlerRegisteredException(messageType);
99 : throw new InvalidOperationException("No handler registered.");
100 : }
101 :
102 : return null;
103 : }
104 :
105 0 : public RouteHandlerDelegate GetSingleHandler<TMessage>(TMessage message, bool throwExceptionOnNoRouteHandlers = true)
106 : where TMessage : IMessage
107 : {
108 : Route route;
109 : Type messageType = message.GetType();
110 : bool isACommand = IsACommand(messageType);
111 :
112 : if (Routes.TryGetValue(messageType, out route))
113 : {
114 : if (route.Handlers != null)
115 : {
116 : if (route.Handlers.Count > 1)
117 : {
118 : if (isACommand)
119 : throw new MultipleCommandHandlersRegisteredException(messageType);
120 : throw new InvalidOperationException("Cannot send to more than one handler.");
121 : }
122 : if (route.Handlers.Count == 1)
123 : return route.Handlers.Single();
124 : }
125 : }
126 :
127 : if (throwExceptionOnNoRouteHandlers)
128 : {
129 : if (isACommand)
130 : throw new NoCommandHandlerRegisteredException(messageType);
131 : throw new InvalidOperationException("No handler registered.");
132 : }
133 :
134 : return null;
135 : }
136 :
137 0 : public IEnumerable<RouteHandlerDelegate> GetHandlers<TMessage>(TMessage message, bool throwExceptionOnNoRouteHandlers = true)
138 : where TMessage : IMessage
139 : {
140 : Route route;
141 : Type messageType = message.GetType();
142 : if (Routes.TryGetValue(messageType, out route))
143 : return route.Handlers;
144 :
145 : if (throwExceptionOnNoRouteHandlers)
146 : {
147 : bool isACommand = IsACommand(messageType);
148 : bool isAnEvent = IsAnEvent(messageType);
149 :
150 : if (isACommand)
151 : throw new NoCommandHandlerRegisteredException(messageType);
152 : if (isAnEvent)
153 : throw new NoEventHandlerRegisteredException(messageType);
154 : throw new NoHandlerRegisteredException(messageType);
155 : }
156 :
157 : return Enumerable.Empty<RouteHandlerDelegate>();
158 : }
159 :
160 0 : protected virtual bool IsACommand<TMessage>(TMessage message)
161 : {
162 : Type messageType = message.GetType();
163 : return IsACommand(messageType);
164 : }
165 :
166 0 : protected virtual bool IsACommand(Type messageType)
167 : {
168 : bool isACommand = false;
169 : Type messageCommandInterface = messageType.GetInterfaces().FirstOrDefault(type => type.FullName.StartsWith(CommandType.FullName));
170 : if (messageCommandInterface != null)
171 : {
172 : Type[] genericArguments = messageCommandInterface.GetGenericArguments();
173 : if (genericArguments.Length == 1)
174 : isACommand = CommandType.MakeGenericType(genericArguments.Single()).IsAssignableFrom(messageType);
175 : }
176 :
177 : return isACommand;
178 : }
179 :
180 0 : protected virtual bool IsAnEvent<TMessage>(TMessage message)
181 : {
182 : Type messageType = message.GetType();
183 : return IsACommand(messageType);
184 : }
185 :
186 0 : protected virtual bool IsAnEvent(Type messageType)
187 : {
188 : bool isAnEvent = false;
189 : Type messageCommandInterface = messageType.GetInterfaces().FirstOrDefault(type => type.FullName.StartsWith(EventType.FullName));
190 : if (messageCommandInterface != null)
191 : {
192 : Type[] genericArguments = messageCommandInterface.GetGenericArguments();
193 : if (genericArguments.Length == 1)
194 : isAnEvent = EventType.MakeGenericType(genericArguments.Single()).IsAssignableFrom(messageType);
195 : }
196 :
197 : return isAnEvent;
198 : }
199 : }
200 : }
|