【.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();
		}
	}
}
相关推荐
2501_933670798 小时前
2026秋招数据分析岗备考路线:SQL、BI、项目与面试题拆解
数据库
我要见SA姐111 小时前
告别 Copilot?Codex 本地化部署指南
运维·数据库·机器学习·oracle·回归
xcLeigh11 小时前
聊聊国产化替换:好用数据迁移工具KDMS怎么帮咱们搞定评估难
数据库·sql·数据迁移·kes·kdms
Elastic 中国社区官方博客12 小时前
列式存储并不等同于列式数据库。Columnar 模式为 Elasticsearch 带来了什么
大数据·运维·数据库·elasticsearch·搜索引擎
我要见SA姐112 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
数据库·ide·vscode·oracle·编辑器
Nturmoils14 小时前
一份 KDMS 评估报告,怎样排出迁移先后顺序
数据库
这个DBA有点耶14 小时前
异构数据集成怎么做?5 种同步方案对比 + 金融级 CDC 实战解析
数据库·oracle·架构
独泪了无痕14 小时前
SQL函数实战:GREATEST与LEAST的技巧
数据库·sql·mysql
码少女14 小时前
Linux--多路转接之select
java·服务器·数据库
梁辰兴14 小时前
软件工程:软件维护的副作用
数据库·软件工程·梁辰兴·控制方法·软件维护的副作用·副作用类型·副作用原因