using EasyNetQ; using EasyNetQ.Topology; using RabbitMQHelper.Attributes; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using RabbitMQHelper.Models; using MongoDB.Driver; namespace RabbitMQHelper { public class MQHostedService : BackgroundService { private readonly IServiceProvider _serviceProvider; private readonly IBus _bus; private readonly IRabbitConfig _mongoDBConfig; private readonly IMongoCollection _collection; private static readonly object lockHelper = new object(); public MQHostedService(IServiceProvider serviceProvider, IBus bus, IRabbitConfig mongoDBConfig) { _serviceProvider = serviceProvider; _bus = bus; _mongoDBConfig = mongoDBConfig; var database = new MongoClient(_mongoDBConfig.MongoConnectionString).GetDatabase(_mongoDBConfig.MongoDatabaseName); _collection = database.GetCollection("mq_receive_record"); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var executorDescriptorList = new List(); foreach (Type ty in _mongoDBConfig.ListSubscribe) { executorDescriptorList.AddRange(GetTopicAttributesDescription(ty.GetTypeInfo())); } var exchange = await _bus.Advanced.ExchangeDeclareAsync(_mongoDBConfig.DefaultExchange, ExchangeType.Topic); foreach (var item in executorDescriptorList) { using (var scope = _serviceProvider.GetRequiredService().CreateScope()) { var topic = item.Attribute.Topic; var provider = scope.ServiceProvider; var obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, item.ImplTypeInfo.GetTypeInfo()); var subscriptId = $"{ item.ClassName.ToLower() }.{item.MethodInfo.Name.ToLower()}"; var queue = await _bus.Advanced.QueueDeclareAsync(subscriptId); await _bus.Advanced.BindAsync(exchange, queue, topic, null); _bus.Advanced.Consume(queue, (msg, info) => Task.Factory.StartNew(async () => { await ReceiveMessage(msg.Body, info.Queue, info.RoutingKey); lock (lockHelper) { object[] parameters = new object[] { msg.Body.Data, msg.Body.Headers }; item.MethodInfo.Invoke(obj, parameters); } })); //await _bus.PubSub.SubscribeAsync(subscriptId, async msg => //{ // await ReceiveMessage(msg, subscriptId, topic); // object[] parameters = new object[] { msg.Data, msg.Headers }; // item.MethodInfo.Invoke(obj, parameters); //}, x => x.WithTopic(topic).w); } } await Task.Delay(Timeout.Infinite, stoppingToken); } public async Task ReceiveMessage(RabbitMessage msg,string subscriptId,string topic) { try { //var database = new MongoClient(_mongoDBConfig.MongoConnectionString).GetDatabase(_mongoDBConfig.MongoDatabaseName); //var collection = database.GetCollection("mq_receive_record"); await _collection.InsertOneAsync(new ReceiveRecord(msg.RecordId, subscriptId, topic)); } catch (Exception ex) { } } private IEnumerable GetTopicAttributesDescription(TypeInfo typeInfo) { foreach (var method in typeInfo.DeclaredMethods) { var topicAttr = method.GetCustomAttributes(true); var topicAttributes = topicAttr as IList ?? topicAttr.ToList(); if (!topicAttributes.Any()) { continue; } foreach (var attr in topicAttributes) { yield return InitDescriptor(attr, method, typeInfo, typeInfo.Name); } } } private ConsumerExecutorDescriptor InitDescriptor(RabbitMQAttribute attr, MethodInfo methodInfo, TypeInfo implType, string name) { var descriptor = new ConsumerExecutorDescriptor { Attribute = attr, MethodInfo = methodInfo, ImplTypeInfo = implType, ClassName = name }; return descriptor; } } }