【.net core】【watercloud】处理rabbitmq类初始化时获取系统已注入的数据库连接问题(调用已注入服务)

问题:需要在RABBITMQ事件处理类中调用系统内业务服务的方法,但在调用方法时获取不到(ISqlSugarClient context)参数导致创建的系统服务为空

路径:WaterCloud.Service\Infrastructure\ServiceSetup.cs

原代码:

cs 复制代码
/// <summary>
/// 注册事件总线
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddEventBus(this IServiceCollection services)
{
    // 注册 EventBus 服务
    return services.AddEventBus(builder =>
    {
        if (GlobalContext.SystemConfig.RabbitMq.Enabled)
        {
            // 创建连接工厂
            var factory = new ConnectionFactory
            {
                HostName = GlobalContext.SystemConfig.RabbitMq.HostName,
                VirtualHost = GlobalContext.SystemConfig.RabbitMq.VirtualHost,
                Port = GlobalContext.SystemConfig.RabbitMq.Port,
                UserName = GlobalContext.SystemConfig.RabbitMq.UserName,
                Password = GlobalContext.SystemConfig.RabbitMq.Password
            };
            // 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus
            var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "OrderTimeLimit", 3000);
            // 替换默认事件总线存储器
            builder.ReplaceStorer(serviceProvider =>
            {
                return rbmqEventSourceStorer;
            });
        }
        // 注册 ToDo 事件订阅者
        builder.AddSubscriber<LogEventSubscriber>();
        builder.AddSubscriber<MessageEventSubscriber>();
    });
}

修改后:

cs 复制代码
/// <summary>
/// 注册事件总线
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddEventBus(this IServiceCollection services)
{
    // 注册 EventBus 服务
    return services.AddEventBus(builder =>
    {
        if (GlobalContext.SystemConfig.RabbitMq.Enabled)
        {
            // 1. 注册 RabbitMQ 连接工厂(单例)
            services.AddSingleton(new ConnectionFactory
            {
                HostName = GlobalContext.SystemConfig.RabbitMq.HostName,
                VirtualHost = GlobalContext.SystemConfig.RabbitMq.VirtualHost,
                Port = GlobalContext.SystemConfig.RabbitMq.Port,
                UserName = GlobalContext.SystemConfig.RabbitMq.UserName,
                Password = GlobalContext.SystemConfig.RabbitMq.Password
            });

            // 2. 关键:替换存储器 → 从 serviceProvider 里解析获取,而不是提前 new
            builder.ReplaceStorer(serviceProvider =>
            {
                // 这里才是真正能拿到 ISqlSugarClient 的地方!
                var sqlSugarClient = serviceProvider.GetRequiredService<ISqlSugarClient>();
                var connectionFactory = serviceProvider.GetRequiredService<ConnectionFactory>();

                // 在这里 new,才能注入 SqlSugar
                return new RabbitMQEventSourceStorer(
                    sqlSugarClient,
                    connectionFactory,
                    "OrderTimeLimit",
                    3000
                );
            });
        }

        // 事件订阅者
        builder.AddSubscriber<LogEventSubscriber>();
        builder.AddSubscriber<MessageEventSubscriber>();
    });
}

RabbitMQEventSourceStorer类中修改:

BusinessorderService为系统业务服务类,初始化时需要提供ISqlSugarClient类型参数,在RabbitMQEventSourceStorer的构造函数中增加ISqlSugarClient类型参数,在调用构造函数时注入

cs 复制代码
using Jaina;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using WaterCloud.Code;
using WaterCloud.Domain.OrderManager;
using WaterCloud.Service.OrderManager;


namespace WaterCloud.Service.Event
{
	public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
	{
        
        private BusinessorderService businessorderService { get; set; }//系统业务服务类
		/// <summary>
		/// 内存通道事件源存储器
		/// </summary>
		private readonly Channel<IEventSource> _channel;
		/// <summary>
		/// 通道对象
		/// </summary>
		private readonly IModel _model;
		/// <summary>
		/// 连接对象
		/// </summary>
		private readonly IConnection _connection;
		/// <summary>
		/// 路由键
		/// </summary>
		private readonly string _routeKey;
        /// <summary>
        /// 构造函数
        /// 在构造函数中增加ISqlSugarClient 参数以初始化BusinessorderService服务类
        /// </summary>
        /// <param name="factory">连接工厂</param>
        /// <param name="routeKey">路由键</param>
        /// <param name="capacity">存储器最多能够处理多少消息,超过该容量进入等待写入</param>
        public RabbitMQEventSourceStorer(ISqlSugarClient context,ConnectionFactory factory, string routeKey, int capacity)
		{

            businessorderService = new BusinessorderService(context);
            // 配置通道,设置超出默认容量后进入等待
            var boundedChannelOptions = new BoundedChannelOptions(capacity)
			{
				FullMode = BoundedChannelFullMode.Wait
			};
			// 创建有限容量通道
			_channel = Channel.CreateBounded<IEventSource>(boundedChannelOptions);
			// 创建连接
			_connection = factory.CreateConnection();
			_routeKey = routeKey;
			// 创建通道
			_model = _connection.CreateModel();
			var arguments = new Dictionary<string, object>
						 {
							 { "x-delayed-type", "direct" }
						 };
			_model.ExchangeDeclare(exchange: "OrderTimeLimitExchange", type: "x-delayed-message", arguments: arguments);
			//_model.ExchangeDeclare(exchange: "OrderTimeLimitExchange", type: "direct");
			// 声明路由队列
			//_model.QueueDeclare(routeKey, false, false, false, null);
			_model.QueueDeclare(queue: routeKey, durable: true, exclusive: false, autoDelete: false, arguments: null);
			_model.QueueBind(queue: routeKey, exchange: "OrderTimeLimitExchange", routingKey: routeKey);
			// 创建消息订阅者
			var consumer = new EventingBasicConsumer(_model);
			// 订阅消息并写入内存 Channel
			consumer.Received += async (ch, ea) =>
			{
                
                try
                {
                    // 读取原始消息
                    var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());
                    // 转换为 IEventSource,这里可以选择自己喜欢的序列化工具,如果自定义了 EventSource,注意属性是可读可写
                    var eventSource = JsonConvert.DeserializeObject<BaseEventSource>(stringEventSource);
                    BusinessorderEntity order = JsonConvert.DeserializeObject<BusinessorderEntity>(stringEventSource);
                    if (order.limitedTimeType.Equals(LimitedTimeType.PayTimeLimit.ToInt()))
                    {
						await businessorderService.PayTimeLimitRabbitMqCallBack(order);
                        LogHelper.WriteWithTime($"订单【{order.orderCode}】,Received方法处理【支付】消息");
                    }
                    else if (order.limitedTimeType.Equals(LimitedTimeType.TKSX.ToInt()))
                    {
                        await businessorderService.RefundTimeLimitRabbitMqCallBack(order);
                        LogHelper.WriteWithTime($"订单【{order.orderCode}】,Received方法处理【退款】消息");
                    }
                    else
                    {
                        await businessorderService.DistributionTimeLimitRabbitMqCallBack(order);
                        LogHelper.WriteWithTime($"订单【{order.orderCode}】,Received方法处理【分配】消息");
                    }
                }
                catch (Exception ex)
                {
                    // 异常:拒绝消息,重新入队
                    _model.BasicNack(ea.DeliveryTag, false, true);
                    // 记录日志
                    Console.WriteLine($"消息处理异常:{ex.Message}");
                }
            };
			// 启动消费者 设置为手动应答消息
			_model.BasicConsume(routeKey, false, consumer);
		}
		/// <summary>
		/// 将事件源写入存储器
		/// </summary>
		/// <param name="eventSource">事件源对象</param>
		/// <param name="cancellationToken">取消任务 Token</param>
		/// <returns><see cref="ValueTask"/></returns>
		public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)
		{
			// 空检查
			if (eventSource == default)
			{
				throw new ArgumentNullException(nameof(eventSource));
			}
			// 这里判断是否是 ChannelEventSource 或者 自定义的 EventSource
			if (eventSource is ChannelEventSource source)
			{
				// 序列化,这里可以选择自己喜欢的序列化工具
				var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(source));
				// 发布
				_model.BasicPublish("", _routeKey, null, data);
			}
			else
			{
				// 这里处理动态订阅问题
				await _channel.Writer.WriteAsync(eventSource, cancellationToken);
			}
		}
		/// <summary>
		/// 从存储器中读取一条事件源
		/// </summary>
		/// <param name="cancellationToken">取消任务 Token</param>
		/// <returns>事件源对象</returns>
		public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)
		{
			// 读取一条事件源
			var eventSource = await _channel.Reader.ReadAsync(cancellationToken);
			return eventSource;
		}
		/// <summary>
		/// 释放非托管资源
		/// </summary>
		public void Dispose()
		{
			_model.Dispose();
			_connection.Dispose();
		}
	}
}
相关推荐
z4424753262 小时前
Go 中高效过滤结构体切片:基于用户名集合的 O(n+m) 算法实现
jvm·数据库·python
m0_617881422 小时前
检测 Python 游戏中三位随机数的数字重复情况并计算胜率倍数
jvm·数据库·python
咸鱼翻身小阿橙2 小时前
Qt P5
开发语言·数据库·qt
2401_887724502 小时前
如何正确在CSS中加载本地JPG背景图片
jvm·数据库·python
Francek Chen2 小时前
【IoTDB】工业物联网时序数据库优选:Apache IoTDB的显著优势
大数据·数据库·物联网·时序数据库·iotdb
lzqk120002 小时前
RabbitMQ 客户端 连接、发送、接收处理消息
分布式·rabbitmq·ruby
weixin_381288182 小时前
mysql如何优化索引以减少扫描_mysql高效索引设计原则
jvm·数据库·python
2401_897190552 小时前
golang如何实现SSRF防护策略_golang SSRF防护策略实现方案
jvm·数据库·python
xxjj998a2 小时前
Spring Boot 实战:轻松实现文件上传与下载功能
java·数据库·spring boot