[英]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.