我正在编写基于TCP连接的DLL
基本前提是它可以被任何客户端使用,并且所有客户端需要做的是提供IP地址和端口号,然后dll负责连接,传输消息,检测断开连接等。
该dll公开了3个事件Connected
,Disconnected
和MessageReceived
客户端只需连接这些事件即可使用它。
DLL还定义了一个基类Message
- 类客户端可以继承,然后将它们自己的类/对象传递给DLL进行发送/接收。
在dll中我定义了Packet
- 类和支持类型:
[Serializable]
internal class Packet
{
private MessageType _type;
private MessageItem _item;
public MessageType MYtpe
{
get
{
return _type;
}
set
{
_type = value;
}
}
//similar for MessageItem
// ...
}
枚举:
public enum MessageType
{
None,
PollItem,
Binary1,
Binary2
}
和对象/类发送的基类:
public abstract class MessageItem
{
}
我的低级别,发送隐藏在DLL中的类,代码,然后就是这个(没有错误处理)
internal bool SendPacket(Packet p)
{
bool sentOk = false;
BinaryFormatter bin = new BinaryFormatter();
try
{
bin.Serialize(theNetworkStream, p);
}
catch etc..
}
ReadPacket
基本上与此相反。
dll公开一个函数供客户端使用,构造数据包并调用上面的发送函数
public void SendMessage(MessageType type, MessageItem message)
现在为客户。 因为我在DLL中定义了2个二进制枚举类型,所以我可以在客户端代码中使用2个单独的类。
e.g。
public class Employee : MessageItem
{
string name;
//etc
}
并且说:
public class Car : MessageItem
{
string Model;
//etc
}
这一切都有效,我可以通过以下方式接收这两种类型中的任何一种:
if(myConnection.NextMessageType() == MessageType.Binary1)
{
Employee e = (Employee)myConnection.ReadMessage();
}
if(myConnection.NextMessageType() == MessageType.Binary2)
{
Car c = (Car)myConnection.ReadMessage();
}
只要客户始终将Employee
类型binary1
和Car
作为binary2
发送。
如果我想发送第三种类型的对象/类,那么我必须进入dll,添加一个枚举; binary3
,重建dll,然后我可以在我的客户端再次派生并在上面的接收代码中使用第3个if
- 子句。
if(myConnection.NextMessageType() == MessageType.Binary3)
{
Animal a = (Animal)myConnection.ReadMessage();
}
所以最后我的问题!
有没有办法可以避免重建DLL,但客户端可以通过DLL发送尽可能多的不同类类型,DLL中的发送/接收机制(从客户端隐藏)仍然可以工作?
我还认为if messagetype == 1, 2 3
等的长列表突出了一个糟糕的设计,但我不知道更好的设计会是什么。
如果你走得这么远,明白我在问什么,谢谢!真的很感激解决方案。
答案 0 :(得分:0)
最简单的解决方案是将MessageType枚举更改为字符串并完全删除枚举。改变: -
public void SendMessage(MessageType type, MessageItem message)
只是: -
public void SendMessage(MessageItem message)
然后将SendPacket更改为:
internal bool SendPacket(Packet p)
{
bool sentOk = false;
BinaryFormatter bin = new BinaryFormatter();
try
{
bin.write (p.MessageItem.GetType ().Name); // or whatever the write/serialise function is called
bin.Serialize(theNetworkStream, p);
}
catch etc..
}
然后,接收器首先读取字符串,然后使用反射创建该类型的对象,然后以伪代码反序列化到对象中:
string message_type = ethernet.readstring ();
Type item_type = convert_name_to_object_type;
ConstructorInfo constructor = item_type.GetConstructor ();
object item = constructor.Invoke ();
ethernet.Deserialise (item);
invoke MessageReceived event (item);
最后一部分可以使用SortedDicationary <message type name, message handler delegate>
将消息分派给正确的处理程序(但这会强制处理程序将MessageItem参数强制转换为正确的消息类型)。或者,再次使用反射来查找名为“HandleEthernetMessage”的方法,该方法接受通过以太网接收的类型的一个参数。 SortedDicationary <message type name, method info>
会在运行时更快,并克服第一个SortedDictionary问题。