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

C#7.3中如何切换不同示波器SDK的using指令以兼容多设备?

解决方案:适配器模式+统一抽象接口

针对你遇到的多SDK兼容问题,最适合的方案是适配器模式+统一抽象接口,既能屏蔽不同SDK的静态方法、枚举、委托差异,又能避免代码冗余,具体实现步骤如下:

1. 定义统一抽象接口与通用类型

先把示波器的核心操作抽象成接口,同时自定义通用枚举、委托,屏蔽不同SDK的类型差异:

// 通用枚举:统一不同SDK的触发模式定义
public enum OscilloscopeTriggerMode
{
    Edge,
    Pulse
    // 根据需求扩展其他模式
}

// 通用回调委托:统一数据采集回调的签名
public delegate void DataCaptureCallback(IntPtr deviceHandle, IntPtr dataBuffer, int dataLength, IntPtr userContext);

// 核心操作接口:定义所有示波器都需要实现的功能
public interface IOscilloscope
{
    int OpenDevice();
    void CloseDevice(int deviceHandle);
    bool ConfigureTrigger(int deviceHandle, OscilloscopeTriggerMode triggerMode);
    void StartDataCapture(int deviceHandle, DataCaptureCallback captureCallback);
    // 根据业务需求添加更多操作方法
}

2. 为每个SDK实现适配器类

针对PS3000和PS5000分别编写适配器,封装各自的静态SDK调用,同时完成类型转换:

PS3000 适配器

public class PS3000OscilloscopeAdapter : IOscilloscope
{
    public int OpenDevice()
    {
        // 直接调用PS3000 SDK的静态方法
        return PS3000AImports.OpenDevice();
    }

    public void CloseDevice(int deviceHandle)
    {
        PS3000AImports.CloseDevice(deviceHandle);
    }

    public bool ConfigureTrigger(int deviceHandle, OscilloscopeTriggerMode triggerMode)
    {
        // 将通用枚举转换为PS3000 SDK的枚举
        var ps3000TriggerMode = triggerMode switch
        {
            OscilloscopeTriggerMode.Edge => PS3000AImports.TriggerMode.EdgeTrigger,
            OscilloscopeTriggerMode.Pulse => PS3000AImports.TriggerMode.PulseTrigger,
            _ => PS3000AImports.TriggerMode.EdgeTrigger
        };
        // 调用SDK方法并返回结果
        return PS3000AImports.SetTrigger(deviceHandle, ps3000TriggerMode) == 0;
    }

    public void StartDataCapture(int deviceHandle, DataCaptureCallback captureCallback)
    {
        // 将通用回调转换为PS3000 SDK的委托类型
        PS3000AImports.PS3000DataCallback sdkCallback = (h, data, len, userData) =>
        {
            captureCallback(h, data, len, userData);
        };
        PS3000AImports.StartCapture(deviceHandle, sdkCallback);
    }
}

PS5000 适配器

public class PS5000OscilloscopeAdapter : IOscilloscope
{
    public int OpenDevice()
    {
        return PS5000AImports.OpenDevice();
    }

    public void CloseDevice(int deviceHandle)
    {
        PS5000AImports.CloseDevice(deviceHandle);
    }

    public bool ConfigureTrigger(int deviceHandle, OscilloscopeTriggerMode triggerMode)
    {
        var ps5000TriggerMode = triggerMode switch
        {
            OscilloscopeTriggerMode.Edge => PS5000AImports.TriggerType.Edge,
            OscilloscopeTriggerMode.Pulse => PS5000AImports.TriggerType.PulseWidth,
            _ => PS5000AImports.TriggerType.Edge
        };
        return PS5000AImports.ConfigureTrigger(deviceHandle, ps5000TriggerMode) == 0;
    }

    public void StartDataCapture(int deviceHandle, DataCaptureCallback captureCallback)
    {
        PS5000AImports.DataReadyCallback sdkCallback = (h, data, len, userData) =>
        {
            captureCallback(h, data, len, userData);
        };
        PS5000AImports.InitiateCapture(deviceHandle, sdkCallback);
    }
}

3. 用工厂模式快速创建实例

通过工厂类封装适配器的创建逻辑,根据设备类型动态生成对应的实例:

public static class OscilloscopeFactory
{
    public static IOscilloscope Create(string deviceSeries)
    {
        return deviceSeries.ToLowerInvariant() switch
        {
            "ps3000" => new PS3000OscilloscopeAdapter(),
            "ps5000" => new PS5000OscilloscopeAdapter(),
            _ => throw new ArgumentOutOfRangeException(nameof(deviceSeries), "不支持该示波器系列")
        };
    }
}

4. 业务代码仅依赖抽象接口

业务逻辑无需关心具体SDK,直接面向IOscilloscope接口编程,轻松切换设备:

// 示例:初始化并使用示波器
var oscilloscope = OscilloscopeFactory.Create("ps5000");
int deviceHandle = oscilloscope.OpenDevice();

if (deviceHandle != -1)
{
    oscilloscope.ConfigureTrigger(deviceHandle, OscilloscopeTriggerMode.Edge);
    oscilloscope.StartDataCapture(deviceHandle, (handle, buffer, length, context) =>
    {
        // 处理采集到的数据
        Console.WriteLine($"收到{length}字节数据");
    });
}

额外优化建议

  • 若两个SDK有大量重复逻辑,可提取抽象基类,将公共代码放在基类中,适配器仅实现差异部分
  • 复杂的类型转换(如枚举、结构体)可单独封装为转换器类,避免适配器代码臃肿
  • 结合依赖注入容器(如Autofac)管理适配器实例,更灵活地实现设备切换

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:31:11