private void ProcessMultiHandler(MethodInfo method, Type paramType, BusRegistry registry,
                                         IEnumerable <HandlesAttribute> handlesAttributes)
        {
            ValidateReturnTypeIsTask(method);

            foreach (var attr in handlesAttributes)
            {
                ValidateParameterIsAssignableFromType(paramType, attr.Type, method);
                if (EventType.IsAssignableFrom(paramType))
                {
                    registry.AddEventSubscriber(attr.Type, method);
                }
                else if (CommandType.IsAssignableFrom(paramType))
                {
                    registry.AddCommandHandler(attr.Type, method);
                }
            }
        }
        public BusRegistry Bootstrap()
        {
            var registry = new BusRegistry();
            var methods  = HandlerTypes.SelectMany(t => t.GetMethods().Where(m => m.IsPublic));

            foreach (var method in methods)
            {
                var mParams = method.GetParameters();
                if (mParams.Count() != 1)
                {
                    continue;
                }

                var paramType = mParams.First().ParameterType;
                if (CommandType.IsAssignableFrom(paramType))
                {
                    ProcessCommandHandlerMethod(method, paramType, registry);
                }
                else if (EventType.IsAssignableFrom(paramType))
                {
                    ProcessEventHanlderMethod(method, paramType, registry);
                }
                else if (paramType.IsAssignableToGenericType(GenericType))
                {
                    ProcessQueryHanlderMethod(method, paramType, registry);
                }

                var handlesAttributes = method.GetCustomAttributes <HandlesAttribute>();
                if (handlesAttributes.Any())
                {
                    ProcessMultiHandler(method, paramType, registry, handlesAttributes);
                }
            }

            foreach (var validator in ValidtorTypes)
            {
                registry.AddCommandValidator(
                    validator.GetInterfaces()
                    .Single(i => i.IsGenericType && i.GetGenericTypeDefinition() == ValidatorType)
                    .GenericTypeArguments.First(), validator);
            }

            return(registry);
        }
        private void ProcessQueryHanlderMethod(MethodInfo methodInfo, Type methodArgType, BusRegistry registry)
        {
            ValidateReturnTypeIsTaskOf(methodInfo, methodArgType.BaseType.GetGenericArguments()[0]);

            registry.AddQueryHandler(methodArgType, methodInfo);
        }
        private void ProcessEventHanlderMethod(MethodInfo methodInfo, Type methodArgType, BusRegistry registry)
        {
            ValidateReturnTypeIsTask(methodInfo);

            registry.AddEventSubscriber(methodArgType, methodInfo);
        }
        private void ProcessCommandHandlerMethod(MethodInfo methodInfo, Type methodArgType, BusRegistry registry)
        {
            ValidateReturnTypeIsTask(methodInfo);

            registry.AddCommandHandler(methodArgType, methodInfo);
        }