public MessageDistributor(
            NsqBus bus,
            IObjectBuilder objectBuilder,
            ILogger logger,
            MessageHandlerMetadata messageHandlerMetadata
        )
        {
            if (bus == null)
                throw new ArgumentNullException("bus");
            if (objectBuilder == null)
                throw new ArgumentNullException("objectBuilder");
            if (logger == null)
                throw new ArgumentNullException("logger");
            if (messageHandlerMetadata == null)
                throw new ArgumentNullException("messageHandlerMetadata");

            _bus = bus;
            _objectBuilder = objectBuilder;
            _logger = logger;

            _serializer = messageHandlerMetadata.Serializer;
            _handlerType = messageHandlerMetadata.HandlerType;
            _messageType = messageHandlerMetadata.MessageType;
            _messageAuditor = messageHandlerMetadata.MessageAuditor;
            _topic = messageHandlerMetadata.Topic;
            _channel = messageHandlerMetadata.Channel;

            var possibleMethods = _handlerType.GetMethods().Where(p => p.Name == "Handle" && !p.IsGenericMethod);
            foreach (var possibleMethod in possibleMethods)
            {
                var parameters = possibleMethod.GetParameters();
                if (parameters.Length == 1 && parameters[0].ParameterType == _messageType)
                {
                    _handleMethod = possibleMethod;
                    break;
                }
            }

            if (_handleMethod == null)
                throw new Exception(string.Format("Handle({0}) not found on {1}", _messageType, _handlerType));

            if (!_messageType.IsInterface)
            {
                _concreteMessageType = _messageType;
            }
            else
            {
                _concreteMessageType = InterfaceBuilder.CreateType(_messageType);
            }
        }
        public void StartBus()
        {
            // TODO: Needs to move to NsqBus. See below comment about async bus start.
            // TODO: This also makes an assumption nsqd is running locally on port 4151. Convenient for testing and sample
            // TODO: apps, probably shouldn't be used in PROD. This needs to be thought through.
            if (_preCreateTopicsAndChannels)
            {
                const string nsqdHttpAddress = "127.0.0.1:4151";
                var          nsqdHttpClient  = new NsqdHttpClient(nsqdHttpAddress, TimeSpan.FromSeconds(5));

                var wg = new WaitGroup();
                foreach (var tch in GetHandledTopics())
                {
                    foreach (var channel in tch.Channels)
                    {
                        string localTopic   = tch.Topic;
                        string localChannel = channel;

                        wg.Add(1);
                        GoFunc.Run(() =>
                        {
                            try
                            {
                                nsqdHttpClient.CreateTopic(localTopic);
                                nsqdHttpClient.CreateChannel(localTopic, localChannel);
                            }
                            catch (Exception ex)
                            {
                                _nsqLogger.Output(LogLevel.Error,
                                                  string.Format("error creating topic/channel on {0} - {1}", nsqdHttpAddress, ex));
                            }

                            wg.Done();
                        }, "BusConfiguration pre-create topics/channels");
                    }
                }

                wg.Wait();
            }

            if (_busStateChangedHandler != null)
            {
                _busStateChangedHandler.OnBusStarting(this);
            }

            _bus = new NsqBus(
                _topicChannelHandlers,
                _dependencyInjectionContainer,
                _messageTypeToTopicProvider,
                _defaultMessageSerializer,
                _nsqLogger,
                _messageMutator,
                _messageTopicRouter,
                _nsqdPublisher
                );

            _bus.Start();

            // TODO: BusConfiguration should not be responsible for these callbacks. With an async _bus.Start
            // TODO: this will need to be moved to NsqBus.
            if (_busStateChangedHandler != null)
            {
                _busStateChangedHandler.OnBusStarted(this, _bus);
            }
        }