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