You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

35 KiB

修改记录

2024年修改记录

创建获取SN接口 - 遵循DDD设计架构

修改时间: 2024年 修改文件:

  • CoreAgent.Domain/Models/System/DeviceInfo.cs (新建)
  • CoreAgent.Domain/Interfaces/System/IDeviceService.cs (新建)
  • CoreAgent.Infrastructure/Services/System/DeviceService.cs (新建)
  • CoreAgent.Application/Commands/System/GetSerialNumberCommand.cs (新建)
  • CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs (新建)
  • CoreAgent.API/Controllers/SystemController.cs (新建)
  • CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs

修改内容:

  1. 领域层设计

    • 创建 DeviceInfo 模型,包含 SerialNumberTimestamp 字段
    • 定义 IDeviceService 接口,提供获取SN的异步和同步方法
    • 遵循DDD设计原则,接口定义在领域层
  2. 基础设施层实现

    • 实现 DeviceService 类,使用 ISystemCommandExecutor 执行系统命令
    • 支持Windows和Linux系统,自动选择对应的命令
    • Windows: wmic bios get serialnumber /value
    • Linux: cat /sys/class/dmi/id/product_serial
    • 提供完善的错误处理和日志记录
  3. 应用层设计

    • 创建 GetSerialNumberCommand 命令类,返回 ApiActionResult<DeviceInfo>
    • 实现 GetSerialNumberCommandHandler 处理器,返回包装后的结果
    • 使用MediatR模式处理命令
    • 在应用层统一处理成功和错误响应
  4. API层设计

    • 创建 SystemController 控制器,继承 BaseApiController
    • 提供 GET /api/v1/system/serial-number 接口
    • 直接返回应用层的 ApiActionResult<DeviceInfo> 结果
    • 简化控制器逻辑,错误处理在应用层完成
  5. 依赖注入配置

    • CommandServiceExtensions 中注册 IDeviceService
    • 使用作用域生命周期管理
  6. 具体实现:

    // 领域模型
    public class DeviceInfo
    {
        public string SerialNumber { get; set; } = string.Empty;
        public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    }
    
    // 领域接口
    public interface IDeviceService
    {
        Task<DeviceInfo> GetSerialNumberAsync();
        DeviceInfo GetSerialNumber();
    }
    
    // 基础设施实现
    public class DeviceService : IDeviceService
    {
        private readonly ISystemCommandExecutor _commandExecutor;
    
        public async Task<DeviceInfo> GetSerialNumberAsync()
        {
            string command = GetSerialNumberCommand();
            var result = await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource(), 5000);
            return ParseSerialNumber(result.Output);
        }
    }
    
    // 应用层处理器
    public async Task<ApiActionResult<DeviceInfo>> Handle(GetSerialNumberCommand request, CancellationToken cancellationToken)
    {
        var deviceInfo = await _deviceService.GetSerialNumberAsync();
        return ApiActionResult<DeviceInfo>.Ok(deviceInfo, "获取设备序列号成功");
    }
    
    // API控制器
    [HttpGet("serial-number")]
    public async Task<IActionResult> GetSerialNumber()
    {
        var command = new GetSerialNumberCommand();
        var result = await _mediator.Send(command);
        return result;
    }
    
  7. 设计优势:

    • DDD架构: 严格遵循领域驱动设计的分层架构
    • 依赖倒置: 高层模块依赖抽象,不依赖具体实现
    • 单一职责: 每个类都有明确的职责
    • 跨平台支持: 自动识别操作系统并使用对应命令
    • 错误处理: 完善的异常处理和日志记录
    • 可测试性: 接口抽象便于单元测试
    • 可扩展性: 易于添加新的设备信息获取功能

影响范围:

  • 新增系统服务模块
  • 扩展API接口
  • 依赖注入配置更新
  • 命令处理流程扩展

创建MessageTransferProtocolLog模型解决命名冲突

修改时间: 2024年 修改文件:

  • CoreAgent.WebSocketTransport/Models/MessageTransferProtocolLog.cs (新建)
  • CoreAgent.Infrastructure/Services/Network/NetworkProtocolLogObserver.cs

修改内容:

  1. 创建MessageTransferProtocolLog模型

    • CoreAgent.WebSocketTransport 项目中创建新的协议日志模型
    • CoreAgent.ProtocolClient 中的 TransferProtocolLog 区分开
    • 保持相同的字段结构,避免命名冲突
    • 专门用于WebSocket传输层的协议日志数据传输
  2. 修改NetworkProtocolLogObserver转换逻辑

    • OnProtocolLogsReceived 方法中添加类型转换
    • CoreAgent.ProtocolClient.TransferProtocolLog 转换为 CoreAgent.WebSocketTransport.MessageTransferProtocolLog
    • 保持所有字段的完整映射
    • 添加必要的using语句引用
  3. 具体实现:

    // 时间跟踪和性能监控
    var startTime = DateTime.UtcNow;
    
    // 空值检查
    if (logDetails == null)
    {
        _logger.LogWarning("接收到的协议日志为空");
        return;
    }
    
    // 转换为列表以避免多次枚举
    var logList = logDetails.ToList();
    var logCount = logList.Count;
    
    // 空集合检查
    if (logCount == 0)
    {
        _logger.LogDebug("接收到的协议日志集合为空,跳过处理");
        return;
    }
    
    // 类型转换逻辑
    var webSocketLogs = logList.Select(log => new MessageTransferProtocolLog
    {
        Id = log.Id,
        LayerType = log.LayerType.ToString(),
        MessageDetailJson = log.MessageDetailJson,
        CellID = log.CellID,
        IMSI = log.IMSI,
        Direction = log.Direction,
        UEID = log.UEID,
        PLMN = log.PLMN,
        TimeMs = log.TimeMs,
        Timestamp = log.Timestamp,
        Info = log.Info,
        Message = log.Message
    });
    
    // 通道写入状态监控
    var writeSuccess = _ChannelManager.SendChannel.TryWrite(webSocketLogs);
    var processingTime = DateTime.UtcNow - startTime;
    
    if (writeSuccess)
    {
        _logger.LogDebug("协议日志处理成功,数量: {LogCount}, 处理时间: {ProcessingTime}ms", 
            logCount, processingTime.TotalMilliseconds);
    }
    else
    {
        _logger.LogWarning("协议日志写入通道失败,数量: {LogCount}, 处理时间: {ProcessingTime}ms, 通道可能已满或已关闭", 
            logCount, processingTime.TotalMilliseconds);
    }
    
  4. 设计优势:

    • 命名清晰MessageTransferProtocolLog 明确表示用于消息传输
    • 避免冲突:与原始 TransferProtocolLog 有明确区分
    • 职责分离:WebSocket传输层有独立的协议日志模型
    • 类型安全:通过显式转换确保类型安全
    • 易于维护:清晰的命名约定便于理解和维护
    • 性能监控:添加时间跟踪和通道写入状态监控
    • 错误处理:完善的异常处理和日志记录
    • Bug修复:修复空引用检查和多次枚举的性能问题
    • 边界处理:添加空集合检查,避免处理空集合
    • 代码规范:优化ProtocolMessage模型注释,提高代码可读性

影响范围:

  • WebSocket传输层协议日志处理
  • 协议日志观察者模式实现
  • 跨项目类型转换逻辑
  • 协议消息模型注释优化

CellularNetworkService.StartNetworkAsync 方法添加协议客户端配置创建

修改时间: 2024年 修改文件:

  • CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs

修改内容:

  1. 调整执行步骤顺序

    • 将原来的第5.5步改为第6步(创建协议客户端配置)
    • 将WebSocket传输连接移到第7步(在网络配置启动之前)
    • 重新编号后续步骤(8-11步)
    • 优化执行顺序:确保WebSocket连接在网络配置启动之前完成
  2. 添加第7步WebSocket传输连接

    • StartNetworkAsync 方法的第6步(创建协议客户端配置)之后添加第7步
    • 注入 IWebSocketTransport 依赖
    • 创建独立的 StartWebSocketTransportAsync() 方法处理连接逻辑
    • 返回 bool 值表示连接是否成功
    • 添加连接状态检查和错误处理
    • 严格检查:WebSocket连接失败时立即返回失败结果,提示服务端可能未启动
  3. 修复Logger类型问题

    • 添加 ILoggerFactory 依赖注入到构造函数
    • 使用 _loggerFactory.CreateLogger<ProtocolClientConfigFactory>() 创建正确类型的Logger
    • 确保 ProtocolClientConfigFactory 获得正确的Logger实例
  4. 具体实现:

    // 6. 创建协议客户端配置
    var protocolConfigFactory = new ProtocolClientConfigFactory(_loggerFactory.CreateLogger<ProtocolClientConfigFactory>(), _context);
    var configCreated = protocolConfigFactory.CreateFromEntities();
    if (configCreated)
    {
        _logger.LogInformation("协议客户端配置创建成功,共创建 {ConfigCount} 个配置", protocolConfigFactory.ConfigCount);
    }
    else
    {
        _logger.LogWarning("协议客户端配置创建失败");
        return CellularNetworkOperationResult.Failure("协议客户端配置创建失败");
    }
    
    // 7. 启动 WebSocket 传输连接
    var webSocketConnected = await StartWebSocketTransportAsync();
    if (!webSocketConnected)
    {
        _logger.LogError("WebSocket 传输连接启动失败,服务端可能未启动");
        return CellularNetworkOperationResult.Failure("WebSocket 传输连接启动失败,服务端可能未启动");
    }
    _logger.LogInformation("WebSocket 传输连接启动成功");
    
  5. 添加必要的依赖注入

    • 添加 ILoggerFactory loggerFactory 参数到构造函数
    • 添加 IWebSocketTransport webSocketTransport 参数到构造函数
    • 添加 using CoreAgent.Infrastructure.Services.Network; 以支持 ProtocolClientConfigFactory
    • 添加 using CoreAgent.WebSocketTransport.Interfaces; 以支持 IWebSocketTransport
  6. 设计优势:

    • 在IP端点信息准备完成后立即创建协议客户端配置
    • 不依赖网络启动结果,确保配置创建的独立性
    • 在网络配置启动之前启动WebSocket传输连接
    • 提供详细的日志记录便于调试
    • 保持代码的简洁性和可维护性
    • 正确处理Logger类型,避免类型不匹配问题
    • 优化执行顺序,提高错误隔离能力
    • 完善的错误处理机制,确保配置创建失败时及时停止
    • 严格检查机制,WebSocket连接失败时立即停止网络启动流程
    • 方法职责单一,WebSocket连接逻辑独立封装

影响范围:

  • 蜂窝网络启动流程
  • 协议客户端配置管理
  • WebSocket传输服务集成
  • 网络状态监控
  • 依赖注入配置(需要更新服务注册)

CellularNetworkService构造函数添加IProtocolLogObserver依赖

修改时间: 2024年 修改文件:

  • CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs

修改内容:

  1. 添加IProtocolLogObserver依赖注入

    • 在构造函数中添加 IProtocolLogObserver protocolLogObserver 参数
    • 添加私有字段 _protocolLogObserver 存储依赖
    • 添加空值检查和异常抛出
  2. 添加必要的using语句

    • 添加 using CoreAgent.ProtocolClient.ProtocolEngineCore; 以支持 IProtocolLogObserver
  3. 具体实现:

    // 构造函数参数
    public CellularNetworkService(
        // ... 其他参数
        IWebSocketTransport webSocketTransport,
        IProtocolLogObserver protocolLogObserver)
    
    // 私有字段
    private readonly IProtocolLogObserver _protocolLogObserver;
    
    // 构造函数初始化
    _protocolLogObserver = protocolLogObserver ?? throw new ArgumentNullException(nameof(protocolLogObserver));
    
  4. 设计优势:

    • 为后续协议客户端管理提供必要的依赖
    • 保持依赖注入的一致性
    • 提供空值检查确保服务稳定性
    • 为协议日志观察者模式提供支持

影响范围:

  • 蜂窝网络服务依赖注入配置
  • 协议客户端日志观察者集成
  • 服务注册配置更新

StartNetworkAsync方法添加时间跟踪记录

修改时间: 2024年 修改文件:

  • CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs

修改内容:

  1. 添加整体时间跟踪

    • 在方法开始时记录开始时间
    • 在方法结束时计算总耗时并记录
    • 使用UTC时间确保时间一致性
  2. 为每个步骤添加详细时间跟踪

    • 为11个步骤中的每个步骤添加开始和结束时间记录
    • 使用 LogDebug 级别记录每个步骤的耗时
    • 保持原有的 LogInformationLogError 级别日志不变
  3. 具体实现:

    // 方法开始时间跟踪
    var startTime = DateTime.UtcNow;
    _logger.LogInformation("开始启动网络配置 {ConfigKey},开始时间: {StartTime}", key, startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"));
    
    // 每个步骤的时间跟踪
    var stepXStart = DateTime.UtcNow;
    _logger.LogDebug("步骤X开始:[步骤描述]");
    
    // 步骤执行逻辑...
    
    var stepXDuration = (DateTime.UtcNow - stepXStart).TotalMilliseconds;
    _logger.LogDebug("步骤X完成:[步骤描述],耗时: {Duration}ms", stepXDuration.ToString("F2"));
    
    // 方法结束时间跟踪
    var endTime = DateTime.UtcNow;
    var duration = endTime - startTime;
    _logger.LogInformation("蜂窝网络配置 {ConfigKey} 启动成功,当前状态: {Status},总耗时: {Duration}ms", 
        key, state.CurrentStatus, duration.TotalMilliseconds.ToString("F2"));
    
  4. 设计优势:

    • 性能监控:可以识别网络启动过程中的性能瓶颈
    • 调试支持:详细的时间信息有助于问题定位和性能优化
    • 日志分级:使用Debug级别避免生产环境日志过多
    • 时间精度:使用毫秒级精度提供准确的性能数据
    • UTC时间:确保时间记录的一致性和准确性
    • 非侵入性:不影响原有的业务逻辑和错误处理
  5. 跟踪的步骤:

    • 步骤1:获取并验证网络配置
    • 步骤2:执行网络接口初始化命令
    • 步骤3:复制配置值到临时目录
    • 步骤4:获取并验证 IP 端点信息
    • 步骤5:更新 IP 端点管理器
    • 步骤6:创建协议客户端配置
    • 步骤7:启动 WebSocket 传输连接
    • 步骤8:启动网络配置
    • 步骤9:更新网络配置类型
    • 步骤10:检查网络端点连接状态
    • 步骤11:更新网络状态

影响范围:

  • 网络启动性能监控
  • 调试和问题定位
  • 日志记录详细程度
  • 性能优化分析

ProtocolWsClientManager方法参数优化

修改时间: 2024年 修改文件:

  • CoreAgent.Infrastructure/Services/Network/ProtocolWsClientManager.cs

修改内容:

  1. 简化构造函数

    • 移除 ProtocolClientConfig[] configs 参数
    • 构造函数只保留必要的依赖:ILoggerIProtocolLogObserverILoggerFactory
    • 移除私有字段 _configs,不再在构造函数中存储配置
  2. 修改StartAllClients方法签名

    • 添加 ProtocolClientConfig[] configs 参数
    • 方法接收配置数组作为参数,而不是依赖构造函数中的配置
    • 添加参数验证,检查 configs 是否为 null 或空数组
  3. 优化方法逻辑

    • 将配置验证移到方法开始处
    • 使用传入的 configs 参数替代私有字段
    • 保持原有的客户端创建和启动逻辑不变
  4. 具体实现:

    // 构造函数简化
    public ProtocolWsClientManager(
        ILogger<ProtocolWsClientManager> logger,
        IProtocolLogObserver protocolLogObserver,
        ILoggerFactory loggerFactory)  // 移除 configs 参数
    
    // StartAllClients方法修改
    public void StartAllClients(ProtocolClientConfig[] configs)  // 添加参数
    {
        if (configs == null || configs.Length == 0)  // 参数验证
        {
            _logger.LogWarning("没有可用的协议客户端配置");
            return;
        }
    
        // 使用传入的 configs 参数
        _logger.LogInformation("开始启动所有协议客户端,配置数量: {ConfigCount}", configs.Length);
        foreach (var config in configs)  // 遍历传入的配置
    
  5. 设计优势:

    • 更灵活的使用方式:可以在不同时间传入不同的配置
    • 减少内存占用:不需要在构造函数中存储配置数组
    • 简化构造函数:降低构造函数的复杂度
    • 更好的测试性:可以更容易地测试不同的配置组合
    • 符合单一职责原则:构造函数只负责初始化,方法负责执行具体操作

影响范围:

  • 协议客户端管理器使用方式
  • 配置传递方式
  • 调用方代码适配
  • 测试用例更新

ProtocolWsClientManager采用面向接口编程

修改时间: 2024年 修改文件:

  • CoreAgent.ProtocolClient/Interfaces/IProtocolWsClientManager.cs (新建)
  • CoreAgent.Infrastructure/Services/Network/ProtocolWsClientManager.cs

修改内容:

  1. 创建IProtocolWsClientManager接口

    • 在CoreAgent.ProtocolClient项目中定义接口契约
    • 继承 IDisposable 接口
    • 定义 StartAllClientsStopAllClients 方法
    • 使用 ProtocolClientConfig[] 作为参数类型
  2. 修改ProtocolWsClientManager实现类

    • 实现 IProtocolWsClientManager 接口
    • 添加 using CoreAgent.ProtocolClient.Interfaces; 引用
    • 保持原有的实现逻辑不变
  3. 具体实现:

    // 接口定义
    public interface IProtocolWsClientManager : IDisposable
    {
        void StartAllClients(ProtocolClientConfig[] configs);
        void StopAllClients();
    }
    
    // 实现类
    public class ProtocolWsClientManager : IProtocolWsClientManager
    {
        // 原有实现保持不变
    }
    
  4. 设计优势:

    • 依赖倒置:高层模块依赖抽象,不依赖具体实现
    • 易于测试:可以轻松创建Mock实现进行单元测试
    • 松耦合:降低组件间的耦合度
    • 可扩展性:可以轻松添加新的实现类
    • 符合SOLID原则:遵循依赖倒置原则和开闭原则
    • 便于依赖注入:可以注册接口而不是具体实现
  5. 接口设计原则:

    • 单一职责:接口只定义协议客户端管理的核心功能
    • 简洁明了:只包含必要的方法定义
    • 易于理解:方法名称和参数清晰明确
    • 向后兼容:保持与原有API的兼容性

影响范围:

  • 依赖注入配置更新
  • 服务注册方式调整
  • 单元测试Mock创建
  • 调用方代码适配(使用接口类型)
  • 项目引用关系调整(CoreAgent.ProtocolClient项目包含接口定义)

CellularNetworkService集成IProtocolWsClientManager

修改时间: 2024年 修改文件:

  • CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs

修改内容:

  1. 添加IProtocolWsClientManager依赖注入

    • 在构造函数中添加 IProtocolWsClientManager protocolWsClientManager 参数
    • 添加私有字段 _protocolWsClientManager 存储依赖
    • 添加空值检查和异常抛出
  2. StartNetworkAsync方法添加第12步

    • 在步骤11(更新网络状态)之后添加第12步
    • 调用 protocolConfigFactory.GetAllConfigs() 获取配置数组
    • 调用 _protocolWsClientManager.StartAllClients(protocolConfigs) 启动所有协议客户端
    • 添加时间跟踪和错误处理
    • 如果启动失败,立即返回失败结果
  3. StopAsync方法集成协议客户端停止

    • 在步骤4(禁用网络配置)之后添加步骤5(停止所有协议客户端)
    • 调用 _protocolWsClientManager.StopAllClients() 停止所有协议客户端
    • 添加错误处理,但不中断停止流程
    • 重新编号后续步骤(6-9步)
  4. 修复StopWebSocketTransportAsync方法

    • 修正方法实现,使用 CloseAsync() 而不是 DisconnectAsync()
    • 修正日志信息和返回值逻辑
    • 确保方法名称和实现一致
  5. 具体实现:

    // 构造函数添加依赖
    public CellularNetworkService(
        // ... 其他参数
        IProtocolWsClientManager protocolWsClientManager)
    
    // StartNetworkAsync第12步
    // 12. 启动所有协议客户端
    var protocolConfigs = protocolConfigFactory.GetAllConfigs();
    _protocolWsClientManager.StartAllClients(protocolConfigs);
    
    // StopAsync步骤5
    // 5. 停止所有协议客户端
    _protocolWsClientManager.StopAllClients();
    
  6. 设计优势:

    • 完整的生命周期管理:启动和停止时都正确处理协议客户端
    • 错误隔离:启动失败时立即停止,停止失败时继续执行
    • 时间跟踪:为协议客户端操作添加详细的时间记录
    • 依赖注入:使用接口编程,便于测试和扩展
    • 日志完整:提供详细的启动和停止日志记录

影响范围:

  • 蜂窝网络服务依赖注入配置
  • 协议客户端生命周期管理
  • 网络启动和停止流程
  • 服务注册配置更新

LogLayerHelp类名规范化

修改时间: 2024年 修改文件:

  • `

ProtocolWsClientManager方法返回类型优化

修改时间: 2024年 修改文件:

  • CoreAgent.Infrastructure/Services/Network/ProtocolWsClientManager.cs
  • CoreAgent.ProtocolClient/Interfaces/IProtocolWsClientManager.cs

修改内容:

  1. StartAllClients方法返回类型修改

    • 将返回类型从 void 改为 bool
    • 添加连接状态检查逻辑,使用 client.IsConnected 判断连接状态
    • 统计已连接的客户端数量
    • 返回 bool 值表示是否所有客户端都成功启动并连接
    • 添加详细的日志记录,包括连接状态信息
  2. StopAllClients方法返回类型修改

    • 将返回类型从 void 改为 bool
    • 添加断开连接状态检查逻辑,使用 client.IsConnected 判断连接状态
    • 记录停止前的连接状态和停止后的连接状态
    • 统计已断开连接的客户端数量
    • 返回 bool 值表示是否所有客户端都成功停止并断开连接
    • 添加详细的日志记录,包括连接状态变化信息
  3. GetAllClientsStatus方法修复

    • 修复语法错误,完善方法实现
    • 添加线程安全锁保护
    • 遍历所有客户端并记录其状态信息
    • 包括客户端名称、连接状态(IsConnected)和客户端状态(State)
    • 添加空客户端检查
  4. 接口定义更新

    • 更新 IProtocolWsClientManager 接口中的方法签名
    • StartAllClients 方法返回 bool 类型
    • StopAllClients 方法返回 bool 类型
    • 添加详细的XML文档注释说明返回值含义
  5. 具体实现:

    // StartAllClients方法
    public bool StartAllClients(ProtocolClientConfig[] configs)
    {
        // 检查连接状态
        if (existingClient.IsConnected)
        {
            connectedCount++;
        }
    
        var allConnected = connectedCount == configs.Length;
        return allConnected;
    }
    
    // StopAllClients方法
    public bool StopAllClients()
    {
        var client = kvp.Value;
        var wasConnected = client.IsConnected;
    
        client.Stop();
    
        // 检查连接状态
        if (!client.IsConnected)
        {
            disconnectedCount++;
        }
    
        var allDisconnected = disconnectedCount == _clients.Count;
        return allDisconnected;
    }
    
    // GetAllClientsStatus方法
    public void GetAllClientsStatus() 
    {
        foreach (var kvp in _clients)
        {
            var client = kvp.Value;
            _logger.LogInformation("客户端状态 - 名称: {ClientName}, 连接状态: {IsConnected}, 客户端状态: {State}", 
                kvp.Key, client.IsConnected, client.State);
        }
    }
    
  6. 设计优势:

    • 状态可追踪:通过返回值可以明确知道操作是否完全成功
    • 连接状态监控:使用 IsConnected 属性准确判断连接状态
    • 详细日志记录:提供完整的操作过程和状态变化日志
    • 线程安全:使用锁保护共享资源访问
    • 错误处理完善:提供详细的错误信息和状态统计
    • 接口一致性:接口和实现保持完全一致
    • 向后兼容:保持方法签名的一致性,只改变返回类型
  7. 返回值含义:

    • StartAllClients 返回 true:所有客户端都成功启动并连接
    • StartAllClients 返回 false:部分或全部客户端启动失败或未连接
    • StopAllClients 返回 true:所有客户端都成功停止并断开连接
    • StopAllClients 返回 false:部分或全部客户端停止失败或仍保持连接

影响范围:

  • 协议客户端管理器接口契约
  • 调用方代码需要处理返回值
  • 网络启动和停止流程的状态判断
  • 日志记录详细程度提升
  • 错误处理和状态监控能力增强

WebSocket传输服务依赖注入修复

修改时间: 2024年 修改文件:

  • CoreAgent.WebSocketTransport/Extensions/WebSocketTransportExtensions.cs
  • CoreAgent.API/Startup.cs

修改内容:

  1. 修复依赖注入顺序问题

    • RegisterDefaultMiddleware 移到 RegisterCoreServices 之前调用
    • 确保中间件在核心服务注册之前就已经注册到容器中
    • 解决 provider.GetServices<IMessageMiddleware>() 无法找到服务的问题
  2. 修复CacheMiddleware注册方式

    • CacheMiddleware 的注册方式从手动工厂方法改为使用 AddWebSocketMiddleware<T>
    • 简化注册逻辑,确保依赖注入容器能正确处理构造函数参数
    • 移除复杂的工厂方法注册,使用标准的依赖注入模式
  3. 添加IMemoryCache服务注册

    • Startup.csConfigureServices 方法中添加 services.AddMemoryCache()
    • 确保 CacheMiddleware 能够正确获取 IMemoryCache 依赖
    • 在 WebSocket 传输服务注册之前添加内存缓存服务
  4. 具体实现:

    // WebSocketTransportExtensions.cs - 调整注册顺序
    public static IServiceCollection AddWebSocketTransport(...)
    {
        // 注册配置
        services.Configure<WebSocketConfig>(...);
    
        // 注册默认中间件(在核心服务之前)
        RegisterDefaultMiddleware(services);
    
        // 注册核心服务
        RegisterCoreServices(services);
    
        return services;
    }
    
    // Startup.cs - 添加内存缓存服务
    public void ConfigureServices(IServiceCollection services)
    {
        // ... 其他服务注册 ...
    
        // 添加内存缓存服务(WebSocket中间件需要)
        services.AddMemoryCache();
    
        // 添加 WebSocket 传输服务
        services.AddWebSocketTransport(Configuration, "WebSocket");
    }
    
  5. 设计优势:

    • 依赖顺序正确:确保中间件在核心服务之前注册
    • 简化注册逻辑:使用标准的依赖注入模式
    • 完整的服务注册:包含所有必要的依赖服务
    • 错误预防:避免运行时依赖注入异常
    • 代码清晰:注册逻辑更加直观和易于理解
  6. 修复的问题:

    • System.InvalidOperationException: Cannot resolve scoped service 'System.Collections.Generic.IEnumerable1[CoreAgent.WebSocketTransport.Middleware.IMessageMiddleware]' from root provider`
    • 依赖注入容器无法找到 IMessageMiddleware 服务
    • CacheMiddleware 无法获取 IMemoryCache 依赖

影响范围:

  • WebSocket传输服务的依赖注入配置
  • 中间件注册和初始化顺序
  • 应用程序启动时的服务注册
  • 内存缓存服务的可用性
  • 错误处理和异常预防

CacheMiddleware构造函数依赖注入修复

修改时间: 2024年 修改文件:

  • CoreAgent.WebSocketTransport/Middleware/CacheMiddleware.cs

修改内容:

  1. 修复构造函数参数类型

    • 将构造函数参数从 WebSocketConfig config 改为 IOptions<WebSocketConfig> config
    • 添加 using Microsoft.Extensions.Options; 引用
    • 在构造函数中通过 config?.Value 获取配置值
  2. 增强空值检查

    • 为所有构造函数参数添加空值检查和异常抛出
    • 使用 ArgumentNullException 确保参数有效性
    • 提供更明确的错误信息
  3. 具体实现:

    // 修复前
    public CacheMiddleware(IMemoryCache cache, ILogger<CacheMiddleware> logger, WebSocketConfig config)
    {
        _cache = cache;
        _logger = logger;
        _config = config;
    }
    
    // 修复后
    public CacheMiddleware(IMemoryCache cache, ILogger<CacheMiddleware> logger, IOptions<WebSocketConfig> config)
    {
        _cache = cache ?? throw new ArgumentNullException(nameof(cache));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _config = config?.Value ?? throw new ArgumentNullException(nameof(config));
    }
    
  4. 设计优势:

    • 正确的依赖注入模式:使用 IOptions<T> 模式获取配置
    • 强化的错误处理:提供详细的空值检查和异常信息
    • 类型安全:确保配置对象正确获取
    • 符合最佳实践:遵循 .NET 依赖注入的标准模式
  5. 修复的问题:

    • Unable to resolve service for type 'CoreAgent.WebSocketTransport.Models.WebSocketConfig'
    • 依赖注入容器无法直接解析 WebSocketConfig 类型
    • 中间件构造函数参数类型不匹配

影响范围:

  • CacheMiddleware的依赖注入配置
  • WebSocket传输服务的启动
  • 配置对象的正确获取
  • 错误处理和异常预防

WebSocket中间件生命周期修复

修改时间: 2024年 修改文件:

  • CoreAgent.WebSocketTransport/Extensions/WebSocketTransportExtensions.cs

修改内容:

  1. 修复生命周期不匹配问题

    • 将中间件注册从 AddScoped 改为 AddTransient
    • 解决单例服务无法解析作用域服务的问题
    • 确保中间件每次使用都创建新实例
  2. 生命周期分析

    • IWebSocketTransport 注册为 Singleton(单例)
    • 中间件注册为 Transient(瞬时)
    • 单例服务可以安全地解析瞬时服务
    • 每次获取中间件都会创建新实例
  3. 具体实现:

    // 修复前
    services.AddScoped<IMessageMiddleware, T>();
    
    // 修复后
    services.AddTransient<IMessageMiddleware, T>();
    
  4. 设计优势:

    • 生命周期兼容:瞬时服务可以被单例服务安全解析
    • 性能优化:中间件每次使用都是新实例,避免状态污染
    • 线程安全:瞬时服务天然线程安全
    • 内存管理:中间件使用完毕后自动释放
  5. 修复的问题:

    • Cannot resolve scoped service 'System.Collections.Generic.IEnumerable1[CoreAgent.WebSocketTransport.Middleware.IMessageMiddleware]' from root provider`
    • 单例服务无法解析作用域服务的依赖注入异常
    • 生命周期不匹配导致的运行时错误
  6. 生命周期说明:

    • Singleton: 整个应用程序生命周期内只有一个实例
    • Scoped: 每个请求作用域内有一个实例
    • Transient: 每次请求都创建新实例
    • 单例服务只能解析瞬时服务,不能解析作用域服务

影响范围:

  • WebSocket中间件的生命周期管理
  • 依赖注入容器的服务解析
  • 应用程序启动时的服务注册
  • 中间件的实例化策略
  • 性能和内存使用优化

DeviceInfo模型添加IsSuccess字段和ParseSerialNumber方法优化

修改时间: 2024年 修改文件:

  • CoreAgent.Domain/Models/System/DeviceInfo.cs
  • CoreAgent.Infrastructure/Services/System/DeviceService.cs
  • CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs

修改内容:

  1. DeviceInfo模型添加IsSuccess字段

    • 添加 bool IsSuccess { get; set; } 属性
    • 用于标识是否成功获取到序列号
    • 提供更准确的成功/失败状态判断
  2. ParseSerialNumber方法优化

    • 返回类型从 string 改为 string?(可空字符串)
    • 失败时返回 null 而不是固定字符串
    • 修复Linux系统输出格式解析:Serial Number: xxxxxxxx
    • 添加更详细的注释说明返回值含义
  3. DeviceService方法更新

    • 修改异步和同步方法中的DeviceInfo创建逻辑
    • 根据ParseSerialNumber返回值设置IsSuccess字段
    • 成功时设置 IsSuccess = true
    • 失败时设置 IsSuccess = false
    • 添加更详细的日志记录
  4. GetSerialNumberCommandHandler优化

    • 在Handle方法中检查 deviceInfo.IsSuccess 字段
    • 成功时返回 ApiActionResult<DeviceInfo>.Ok()
    • 失败时返回 ApiActionResult<DeviceInfo>.Error() 并设置错误代码 DEVICE_SN_NOT_FOUND
    • 提供更准确的错误信息
  5. 具体实现:

    // DeviceInfo模型
    public class DeviceInfo
    {
        public bool IsSuccess { get; set; }
        public string SerialNumber { get; set; } = string.Empty;
        public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    }
    
    // ParseSerialNumber方法
    private string? ParseSerialNumber(string output)
    {
        if (string.IsNullOrWhiteSpace(output))
            return null;
    
        foreach (var line in lines)
        {
            if (OperatingSystem.IsLinux())
            {
                // Linux输出格式: Serial Number: xxxxxxxx
                if (trimmedLine.StartsWith("Serial Number:", StringComparison.OrdinalIgnoreCase))
                {
                    var serialNumber = trimmedLine.Substring("Serial Number:".Length).Trim();
                    return string.IsNullOrWhiteSpace(serialNumber) ? null : serialNumber;
                }
            }
        }
        return null;
    }
    
    // DeviceService中的使用
    if (serialNumber != null)
    {
        return new DeviceInfo
        {
            IsSuccess = true,
            SerialNumber = serialNumber,
            Timestamp = DateTime.UtcNow
        };
    }
    else
    {
        return new DeviceInfo
        {
            IsSuccess = false,
            SerialNumber = "UNKNOWN",
            Timestamp = DateTime.UtcNow
        };
    }
    
    // GetSerialNumberCommandHandler中的使用
    if (deviceInfo.IsSuccess)
    {
        return ApiActionResult<DeviceInfo>.Ok(deviceInfo, "获取设备序列号成功");
    }
    else
    {
        return ApiActionResult<DeviceInfo>.Error("获取设备序列号失败", "DEVICE_SN_NOT_FOUND");
    }
    
  6. 设计优势:

    • 准确的状态判断:通过IsSuccess字段明确标识操作结果
    • 更好的错误处理:区分不同类型的失败情况
    • Linux兼容性:正确解析Linux系统的序列号输出格式
    • 空值安全:使用可空字符串避免固定错误字符串
    • 详细日志:提供更丰富的日志信息便于调试
    • API一致性:返回统一的ApiActionResult格式

影响范围:

  • 设备序列号获取的准确性
  • API响应的错误处理
  • Linux系统兼容性
  • 日志记录的详细程度
  • 客户端错误处理逻辑