Beispiel #1
0
        /// <summary>
        /// Sends the given transport message to the specified destination address using MSMQ. Will use the existing <see cref="MessageQueueTransaction"/> stashed
        /// under the <see cref="CurrentTransactionKey"/> key in the given <paramref name="context"/>, or else it will create one and add it.
        /// </summary>
        public async Task Send(string destinationAddress, TransportMessage message, ITransactionContext context)
        {
            if (destinationAddress == null)
            {
                throw new ArgumentNullException(nameof(destinationAddress));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var logicalMessage = CreateMsmqMessage(message);

            var messageQueueTransaction = context.GetOrAdd(CurrentTransactionKey, () =>
            {
                var transaction = new MessageQueueTransaction();

                transaction.Begin();

                context.OnCommitted(async ctx => transaction.Commit());

                return(transaction);
            });

            var sendQueues = context.GetOrAdd(CurrentOutgoingQueuesKey, () =>
            {
                var messageQueues = new ConcurrentDictionary <string, MessageQueue>(StringComparer.InvariantCultureIgnoreCase);

                context.OnDisposed(ctx =>
                {
                    foreach (var messageQueue in messageQueues.Values)
                    {
                        messageQueue.Dispose();
                    }
                });

                return(messageQueues);
            });

            var path = MsmqUtil.GetFullPath(destinationAddress);

            var sendQueue = sendQueues.GetOrAdd(path, _ =>
            {
                var messageQueue = new MessageQueue(path, QueueAccessMode.Send);

                return(messageQueue);
            });

            try
            {
                sendQueue.Send(logicalMessage, messageQueueTransaction);
            }
            catch (Exception exception)
            {
                throw new RebusApplicationException(exception, $"Could not send to MSMQ queue with path '{sendQueue.Path}'");
            }
        }