//private string BuildInvocationFailureMessage(string methodName, object[] arguments)
        //{
        //	return string.Concat(new string[]
        //	{
        //		"Failed to invoke target method '",
        //		methodName,
        //		"' with argument types = [",
        //		StringUtils.CollectionToCommaDelimitedString<string>(this.GetArgumentTypes(arguments)),
        //		"], values = [",
        //		StringUtils.CollectionToCommaDelimitedString<object>(arguments),
        //		"]"
        //	});
        //}
        //private System.Collections.Generic.List<string> GetArgumentTypes(object[] arguments)
        //{
        //	System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>();
        //	if (arguments != null)
        //	{
        //		for (int i = 0; i < arguments.Length; i++)
        //		{
        //			list.Add(arguments[i].GetType().ToString());
        //		}
        //	}
        //	return list;
        //}

        protected virtual void HandleResult(AmqpBasedRoute replyRoute, List <object> responses)
        {
            if (replyRoute != null)
            {
                this._queueClient.BatchPublish(exchangeName: replyRoute.ExchangeName, routingKey: replyRoute.RoutingKey, contentList: responses);
            }
        }
        public QueuedWorkflowMessageProcessingWorker(IQueueClient queueClient, object listenerObject, MethodInfo listenerMethod, QueuedTransition queuedTransition, QueuedTransition nextQueuedTransition, bool createZombieQueues)
        {
            Contract.Requires(queueClient.IsNotNull(), "No queueClient specified: Either specify a non-null value for the 'queueClient' constructor argument.");
            Contract.Requires(listenerObject.IsNotNull(), "No listenerObject specified: Either specify a non-null value for the 'listenerObject' constructor argument.");
            Contract.Requires(listenerMethod.IsNotNull(), "No listenerMethod specified: Either specify a non-null value for the 'listenerMethod' constructor argument.");
            this._queueClient    = queueClient;
            this._listenerObject = listenerObject;
            this._listenerMethod = listenerMethod;


            Type inType  = this._listenerMethod.GetUniqueAndExpectedInputParameterType();
            Type outType = this._listenerMethod.GetReturnValueType();

            if (outType == typeof(void) || outType == typeof(Task))
            {
                this._canUseRequestAsResponse = true;
            }
            else
            {
                this._canUseRequestAsResponse = outType.IsAssignableFrom(inType);
            }

            //Receive Route é usada para garantir a criação da rota no RabbitMQ
            this.ReceiveRoute = new AmqpBasedRoute()
            {
                ExchangeName = queuedTransition.ExchangeName,                   //Criando ExchangeName Default
                QueueName    = queuedTransition.LogicalQueueName + ".Process",  //Queue de recebimento (Fila Principal)
                RoutingKey   = queuedTransition.BuildRoutingKey()               //Binding Entre a ExchangeName e a Fila
            };
            this.ReceiveRoute.EnsureAll(this._queueClient);

            if (createZombieQueues)
            {
                //Filas Zombie não precisam ser armazenadas em variáveis, só precisam ser configuradas
                //corretamente no RabbitMQ
                AmqpBasedRoute zombieConfiguration = new AmqpBasedRoute()
                {
                    ExchangeName = this.ReceiveRoute.ExchangeName,
                    QueueName    = queuedTransition.LogicalQueueName + ".Zombie",
                    RoutingKey   = this.ReceiveRoute.RoutingKey
                };
                zombieConfiguration.EnsureAll(this._queueClient);
            }

            //Caso não seja um passo final, é necessário armazenar e tratar as respostas para o próximo step
            if (nextQueuedTransition != null)
            {
                this._successResponseRoute = new AmqpBasedRoute()
                {
                    QueueName    = nextQueuedTransition.LogicalQueueName + ".Process",
                    ExchangeName = nextQueuedTransition.ExchangeName,
                    RoutingKey   = nextQueuedTransition.BuildRoutingKey(),
                };
                this._successResponseRoute.EnsureAll(this._queueClient);
            }

            this._errorFlowStrategy = queuedTransition.ErrorFlowStrategy;
            //Nesse passo as estratégias são usadas para configurar o comportamento adequado para falhas
            if (this._errorFlowStrategy == ExceptionStrategy.SendToErrorQueue)
            {
                //Se ao encontrar um erro, é necessário enviar para a fila de erro, todo o pipe de erro é criado
                //isso conta com a criação da fila, e dos bindings no RabbitMQ
                this._failureResponseRoute = new AmqpBasedRoute()
                {
                    QueueName    = queuedTransition.LogicalQueueName + ".Failure",
                    ExchangeName = this.ReceiveRoute.ExchangeName,
                    RoutingKey   = queuedTransition.BuildFailureRoutingKey()
                };
                this._failureResponseRoute.EnsureAll(this._queueClient);
            }
            else if (this._errorFlowStrategy == ExceptionStrategy.Requeue)
            {
                //Nesse caso, ao gerar um erro na fila a mensagem volta para a fila, portanto
                //a rota usada é escolhida como a mesma rota de recebimento, forçando um requeue
                this._failureResponseRoute = this.ReceiveRoute;
            }
            else if (this._errorFlowStrategy == ExceptionStrategy.SendToNextStepQueue)
            {
                //Nesse caso temos a possibilidade de continuar o fluxo, mesmo que uma
                //exceção seja lançada.
                if (this._successResponseRoute == null)
                {
                    throw new InvalidOperationException("The ErrorFlowStrategy property cannot be setted with SendToNextStepQueue value when current step is a final step.");
                }
                this._failureResponseRoute = this._successResponseRoute;
            }
        }