繁体   English   中英

如何在VB.NET中优雅地创建从串口读入的命令对象?

[英]How to elegantly create command objects read in from serial port in VB.NET?

在我的VB.NET程序中,我正在从连接到串行端口的设备读取命令响应。 目前,命令集已修复,但将来可能会添加新命令。 有没有比一个巨大的switch / if-then-else语句更优雅的东西我可以用来读取每个命令并为它们创建一个对象? 我有一个基本的“命令”类,但派生的每个命令拥有特殊功能。

我希望能够制作一个优雅的解决方案,避免每次将新对象添加到命令集时更新巨型switch语句。

这取决于您在线上的消息格式以及如何反序列化它们。 我会做这样的事情(例如在C#中,因为我不使用VB.NET,但它应该很容易转换它)。

每个命令都实现ICommand接口,并从某个CommandBase实现类派生。 CommandBase定义MessageId抽象属性,该属性对于每个命令类型都是唯一的(您也可以使用常量)。 此ID也是线路上消息头的一部分,以便您知道从设备传入的命令。

现在您从设备获取消息ID:

int msgId = ... // what came from the device
Type cmdType = GetTypeForMessage(msgId); // get the corresponding implementation
ICommand cmd = (Command)Activator.CreateInstance(cmdType); // crate an instance
cmd.Deserialize(buffer); // or whatever way you do the serialization
cmd.Execute();  // run the command

您从之前设置的地图中获取了正确的类型:

Type GetTypeForMessage(int msgId) {
    // m_commandMap is Dictionary<int, Type>
    return m_commandMap[msgId];
}

现在剩下的问题是如何设置m_commandMap 一种方法是自动注册从某个CommandBase类派生的所有类。 你在启动时做了这样的事情:

  // find all types in this assembly
  Assembly assembly = Assembly.GetExecutingAssembly();
  foreach (var type in assembly.GetTypes()) {
    if(typeof(CommandBase).IsAssignableFrom(type)) { // which derive from CommandBase
      CommandBase cmd = (CommandBase) Activator.CreateInstance(type);  
      m_commandMap[cmd.MessageId] = type;
      // I would make MessageId a static constant on class and read it
      // using reflection, so I don't have to instantiate an object
    }                    
  }

现在,当您需要实现新命令时,您所要做的就是定义它:

class NewCommand : CommandBase {
    public override int MessageId { get { return 1234; } }
    // or preferably: public const int MessageId = 1234;
    // the rest of the command: ...
}

如果相应的ID来自设备,它将在启动时自动注册并用于反序列化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM