public async Task Publish(IPublisherContext context, CreatedExchange createdExchange,
                                  IMessage message,
                                  CancellationToken cancellationToken)
        {
            // Prepare the message and its defining properties to be published.
            byte[]            messageBody       = context.Serialization.Serialize(message, createdExchange.Definition.ContentType);
            MessageProperties messageProperties = GetMessageProperties(context, createdExchange, message);
            string            routeKey          = message.GetRouteKey() ?? createdExchange.Definition.RouteKey;

            // Only send the message to the exchange if satisfying all constraints configured for the exchange.
            // This only applies to domain-events, as commands are more specific in that they are explicitly
            // requesting a behavior to be taken.
            if (message is IDomainEvent &&
                !await Satisfies(context, createdExchange, message).ConfigureAwait(false))
            {
                return;
            }

            // Delegate to EasyNetQ to publish the message.
            await createdExchange.Bus.Advanced.PublishAsync(createdExchange.Exchange,
                                                            routeKey ?? string.Empty,
                                                            false,
                                                            messageProperties,
                                                            messageBody).ConfigureAwait(false);
        }
        public async Task Publish(IPublisherContext context, CreatedExchange createdExchange,
                                  IMessage message,
                                  CancellationToken cancellationToken)
        {
            ICommand command     = (ICommand)message;
            string   contentType = createdExchange.Definition.ContentType;

            // Serialize the message and get the properties from the default-publisher to be used as
            // the initial list of message properties to which RPC specific properties will be added.
            byte[]            messageBody       = context.Serialization.Serialize(command, contentType);
            MessageProperties messageProperties = DefaultPublisherStrategy.GetMessageProperties(context, createdExchange, command);

            // Get the RPC client associated with the exchange to which the RPC message is being sent.
            IRpcClient client = context.PublisherModule.GetRpcClient(
                createdExchange.Definition.BusName,
                createdExchange.Definition.QueueMeta.QueueName);

            // Note:  Consumer replies with same content-type that was used to publish command.

            try
            {
                // Delegate to the client to send the request and wait for response in reply queue.
                byte[] resultBytes = await client.Publish(createdExchange, messageBody,
                                                          messageProperties,
                                                          cancellationToken).ConfigureAwait(false);

                // If a successful reply, deserialize the response message into the
                // result type associated with the command.
                var responseObj = context.Serialization.Deserialize(contentType, command.ResultType, resultBytes);
                command.SetResult(responseObj);

                LogReceivedRpcResponse(context, createdExchange, responseObj);
            }
            catch (RpcReplyException ex)
            {
                // If the consumer didn't supply details about the exception, then just rethrow.
                if (ex.ReplayExceptionBody == null)
                {
                    throw;
                }

                var dispatchEx = context.Serialization.Deserialize <MessageDispatchException>(contentType, ex.ReplayExceptionBody);
                context.Logger.LogError(RabbitMqLogEvents.PublisherException, dispatchEx, "RPC Exception Reply.");
                throw dispatchEx;
            }
        }
        public static MessageProperties GetMessageProperties(IPublisherContext context,
                                                             CreatedExchange createdExchange,
                                                             IMessage message)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (createdExchange == null)
            {
                throw new ArgumentNullException(nameof(createdExchange));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var definition = createdExchange.Definition;

            var props = new MessageProperties
            {
                ContentType  = definition.ContentType,
                AppId        = context.BusModule.HostAppId,
                Timestamp    = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                DeliveryMode = (byte)(definition.IsPersistent ? 2 : 1)
            };

            string correlationId = message.GetCorrelationId();

            if (correlationId != null)
            {
                props.CorrelationId = correlationId;
            }

            byte?msgPriority = message.GetPriority();

            if (msgPriority != null)
            {
                props.Priority = msgPriority.Value;
            }

            return(props);
        }
        private static async Task <bool> Satisfies(IPublisherContext context, CreatedExchange createdExchange, IMessage message)
        {
            ExchangeMeta definition = createdExchange.Definition;
            bool         applies    = definition.Applies(message);

            if (applies && definition.ScriptPredicate != null)
            {
                return(await context.Scripting.SatisfiesPredicateAsync(message, definition.ScriptPredicate));
            }

            return(applies);
        }