public async Task StartServer(CancellationToken token = default(CancellationToken)) { // Get any available handlers var handlers = new List <HandlerRegistration>(); Type[] handlerTypes = _handlerFactory.GetAllHandlerTypes(); foreach (Type handlerType in handlerTypes) { // Try to get the IHandleMessage<T> interface from the handlerType var handlerInterfaces = handlerType.IsMessageHandlerInterface() ? new Type[] { handlerType } // The handlerType itself is already IHandleMessage<T> : handlerType.GetMessageHandlerInterfaces().ToArray(); // The handlerType should implement IHandleMessage<T> at least once if (handlerInterfaces.Length == 0) { throw new InvalidOperationException($"The handler Type {handlerType.Name} is not a message handler"); } // Get the message Type T from IHandleMessage<T> and create a handler registration by invoking the static factory method // on HandlerRegistration with the appropriate type arguments foreach (Type handlerInterface in handlerInterfaces) { Type messageType = handlerInterface.GenericTypeArguments.Single(); var handler = (HandlerRegistration)HandlerRegistrationFactoryMethod.MakeGenericMethod(handlerType, messageType).Invoke(this, null); handlers.Add(handler); } } // Nothing to do if no handlers if (handlers.Count == 0) { return; } // Get the unique message FullNames amongst the handlers and use those as the topic name to subscribe to Dictionary <string, List <HandlerRegistration> > handlersByTopic = handlers.GroupBy(h => h.MessageDescriptor.FullName) .ToDictionary(g => g.Key, g => g.ToList()); // Subscribe to all topics Subscription[] subscriptions = await Task.WhenAll(handlersByTopic.Select(kvp => Subscribe(kvp.Key, kvp.Value, token))) .ConfigureAwait(false); // Kick off a background task to pull messages off the transport for each subscription and dispatch the messages _runningServer = Task.Run(() => RunServer(subscriptions, _cancelRunningServer.Token), _cancelRunningServer.Token); }