关于 C# 接口和泛化设计的建议

Advice on Interface and generalization design in C#

背景: 我正在寻找一种通用方法来实现 Raspberry Pi IoT 业余项目的标准功能,该项目通过串行通信与不同的硬件设备进行通信。这些设备通过返回它们使用的 "protocol version" 以及它们实施的协议的命令组来识别自己。

Example 1:

  • Device1: "Protocol V1a" Group "a,b"
  • Device2: "Protocol V2" Group "a,c"
  • Device3: and so on...

不同协议中基本支持的命令是相同的,但对于不同的版本,他们期望不同的实现。

Example 2:

  • Protocol V1a:

    • Command group a:
      • void sendAck(){SerialWrite(byte 0x0A);}
      • void sendNak(){SerialWrite(byte 0x00);}
  • Protocol V2:

    • Command group a:
      • void sendAck(){SerialWrite(byte 0x1A);}
      • void sendNak(){SerialWrite(byte 0x10);}

目标: 我的目标是能够将 raspberry pi 运行 应用程序连接到随机设备之一,并在收到协议版本后和设备支持的命令组在代码中创建必要的对象。

目前我取得的成就: 与设备的串行通信有效。我知道不同的命令,但想让它更通用、更灵活。因此,对于命令的基本定义,我创建了一个接口定义。

interface IDeviceProtocol
{
    // Group a commands
    void sendAck();
    void sendNak();

    // Group b commands
    void someOtherCommand();
}

通过这样做,我可以使用接口定义并根据协议实现必要的命令。

class ProtocolV1a: IDeviceProtocol
{
    // Explicit interface member implementation: 
    void IDeviceProtocol.sendAck()
    {
        SerialWrite(byte 0x0A);
    }

    // Explicit interface member implementation: 
    void IDeviceProtocol.sendNak()
    {
        SerialWrite(byte 0x00);
    }

    static void Main()
    {
       // Some protocol specific code here.
    }
}

现在我应该可以在我的主程序中使用以下代码来调用特定协议 class。这是正确的吗?

IDeviceProtocol Device1 = new ProtocolV1a();
Device1.sendAck();

或者如果它是 V2 协议设备:

IDeviceProtocol Device2 = new ProtocolV2();
Device2.sendAck();

问题: 是否有可能列出所有可能的协议版本的某种枚举器列表。并根据设备返回的协议版本创建具有正确协议 class 的设备 class?

像这样:

// returns the protocol used by the device    
    EnumProtocols pversion = ReceiveProtocol(); 

    IDeviceProtocol genericDevice = new IDeviceProtocol(pversion);

    genericDevice.sendAck();

此方法是否有名称以便我可以查找并了解如何操作? 你能给我一些从哪里开始寻找的指示,或者一些示例代码吗?

我认为您正在寻找的是工厂设计模式。

这样的事情可能会实现您的目标:

public enum Protocol
{
    Version1,
    Version1A,
    Version2
}

public IDeviceProtocol CreateDeviceProtocol(Protocol protocol)
{
    switch protocol
    {
        case Protocol.Version1:
            return new Device1();
            break;
        case Protocol.Version1A:
            return new Device1A();
            break;
        case Protocol.Version2:
            return new Device2();
            break;
        default:
            //throw some error  
    }
}