簡體   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