You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SerialPort类实现依赖注入 无法通过ICommand调用其方法

依赖注入解耦SerialPort实现方案

.NET 官方提供的 SerialPort 类没有适配串口操作的专用公开接口,其仅实现的 ICommand 接口不包含任何串口相关的业务成员,无法满足调用需求,因此你需要自定义抽象接口来完成解耦,具体实现步骤如下:

步骤1:自定义串口操作抽象接口

将你业务中用到的所有 SerialPort 成员定义到接口中,示例代码如下:

public interface ISerialPort : IDisposable
{
    // 你用到的DataReceived事件
    event SerialDataReceivedEventHandler DataReceived;
    // 你用到的Open、Close方法
    void Open();
    void Close();
    // 如需获取串口号可补充该属性
    string PortName { get; }
    // 后续如果用到Write、Read等其他SerialPort方法,可在此处补充定义
}

步骤2:实现SerialPort适配类

基于原生SerialPort写适配类,实现你定义的ISerialPort接口:

public class SerialPortAdapter : ISerialPort
{
    private readonly SerialPort _serialPort;

    public SerialPortAdapter(string comPort, int baudRate = 9600, Parity parity = Parity.None, 
        int dataBits = 8, StopBits stopBits = StopBits.One, Handshake handshake = Handshake.None)
    {
        _serialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBits)
        {
            Handshake = handshake
        };
    }

    public event SerialDataReceivedEventHandler DataReceived
    {
        add => _serialPort.DataReceived += value;
        remove => _serialPort.DataReceived -= value;
    }

    public string PortName => _serialPort.PortName;

    public void Open() => _serialPort.Open();

    public void Close() => _serialPort.Close();

    public void Dispose() => _serialPort.Dispose();
}

步骤3:改造原有业务类使用依赖注入

将CommandService的依赖改为抽象接口,不再在构造函数中自行初始化SerialPort实例:

public class CommandService : IDisposable
{
    private readonly ISerialPort _serialPort;

    // 直接注入ISerialPort实例,初始化逻辑交给DI容器处理
    public CommandService(ISerialPort serialPort)
    {
        _serialPort = serialPort;
        try
        {
            _serialPort.Open();
        }
        catch (System.IO.FileNotFoundException)
        {
            throw new Exception($"Serialport {_serialPort.PortName} can't be found");
        }
        _serialPort.DataReceived += DataReceived;
    }

    // 保留你原有的DataReceived业务处理逻辑
    private void DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // 原有业务代码不变
    }

    public void Dispose()
    {
        _serialPort.Close();
        _serialPort.Dispose();
    }
}

步骤4:DI容器注册示例(以.NET默认DI容器为例)

在服务注册处配置串口参数和依赖映射:

// 注册串口实例,按需配置串口参数
services.AddScoped<ISerialPort>(sp => 
    new SerialPortAdapter("COM3", 9600, Parity.None, 8, StopBits.One, Handshake.None));
// 注册业务服务
services.AddScoped<CommandService>();

方案优势

  • 完全解除业务层和原生SerialPort的耦合,单元测试时可直接MockISerialPort接口,无需依赖真实串口硬件
  • 后续需要替换串口实现(比如第三方串口库、虚拟串口模拟)时,只需新增ISerialPort的实现类即可,无需修改业务代码
  • 串口参数、实例生命周期都交由DI容器统一管理,避免硬编码参数

内容的提问来源于stack exchange,提问作者CSharpFan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 19:15:04