/// <summary> /// Объявить очередь. /// </summary> /// <param name="channel">Канал.</param> /// <param name="settings">Настройки подписчика.</param> /// <param name="messageType">Тип сообщения.</param> public void DeclareQueue(IModel channel, SubscriberSettings settings, Type messageType) { var queueName = _namingConvention.QueueNamingConvention(messageType, settings); if (settings.UseDeadLetter) { settings.Arguments[QueueArgument.DEAD_LETTER_EXCHANGE] = _namingConvention.DeadLetterExchangeNamingConvention(messageType, settings); settings.Arguments[QueueArgument.DEAD_LETTER_ROUTING_KEY] = queueName; } if (settings.ScalingSettings.UseSingleActiveConsumer) { settings.Arguments[QueueArgument.SINGLE_ACTIVE_CONSUMER] = true; } channel.QueueDeclare( queueName, settings.Durable, settings.Exclusive, settings.AutoDelete, settings.Arguments ); foreach (var binding in settings.Bindings) { // пустая строка - обменник по-умолчанию. Его создавать нельзя. if (!string.IsNullOrWhiteSpace(binding.FromExchange)) { channel.ExchangeDeclare( binding.FromExchange, durable: settings.Durable, autoDelete: settings.AutoDelete, type: binding.ExchangeType ); } if (string.Equals(binding.ExchangeType, ExchangeType.Fanout, StringComparison.OrdinalIgnoreCase)) { channel.QueueBind( queueName, binding.FromExchange, string.Empty, binding.Arguments ); continue; // для Fanout не требуются routingKeys, 1 биндинг на обменник и всё. } if (string.Equals(binding.ExchangeType, ExchangeType.Headers, StringComparison.OrdinalIgnoreCase) && binding.Arguments.Any()) { channel.QueueBind( queueName, binding.FromExchange, string.Empty, binding.Arguments ); continue; // для Headers не требуются routingKeys, 1 биндинг на обменник без ключей роутинга. А роут вычисляется по аргументам. } // для всех остальных кейсов (direct.. и прочее) foreach (var routingKey in binding.RoutingKeys) { channel.QueueBind( queueName, binding.FromExchange, routingKey, binding.Arguments ); } } }