具有不同消息类型的消息队列

本文关键字:消息 类型 队列 | 更新日期: 2023-09-27 18:35:41

我正在研究Microsoft消息队列来执行进程间跨网络消息传递。但是当我收到一条消息时,我不知道我得到的是哪种类型的对象,所以代码

queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(Wibble) });

在我收到消息之前无法应用,因为我不知道它是否是 Wibble。那么如何接收不同的消息类型呢?

具有不同消息类型的消息队列

你已经在对接受类型数组XmlMessageFormatter使用构造函数重载。因此,只需将您希望接收的所有类型添加到该数组中,而不仅仅是一种类型。

queue.Formatter = new XmlMessageFormatter(new Type[] {
    typeof(Wibble),
    typeof(Fleem),
    typeof(Boo)
});

TargetTypes

在消息正文中序列化的实例必须符合类型数组中表示的架构之一。使用 Receive 方法读取消息时,该方法将创建与标识的架构对应的类型的对象,并将消息正文读入其中。

(着重号后加)

您可以考虑不将对象存储在 MSMQ 消息中,而是尽可能放置对其持久位置的引用。 MSMQ 在消息队列上的空间有限,因此较小的消息是最好的。

如果不能做到这一点,则可以使用您喜欢的任何序列化程序直接将对象序列化为消息 BodyStream。 然后存储类型名称,最好在消息标签中存储。

与此非常相似的东西(在这里划掉了它,这台计算机上没有IDE)把它放进去,以及出路的模拟动作:

public void FormatObject(object toFormat, Message message)
{
    var serializer = new XmlSerializer(toFormat.GetType());
    var stream = new MemoryStream();
    serializer.Serialize(toFormat, stream);
    //don't dispose the stream
    message.BodyStream = stream;
    message.Label = toFormat.GetType().AssemblyQualifiedName;
}

MSMQ 上存在大量错误信息,主要是因为关于如何正确设计消息发送接收的Microsoft文档非常稀疏。我出版了两本关于这个主题的MSMQ书籍,我仍在互联网上寻找明智的设计。

因此,这些引用都没有说队列要求只有一个消息类型。这将使PeakMessage和变体变得不必要,甚至愚蠢。Microsoft在其文档中含糊不清且困难,但我在那里工作过,他们从不愚蠢。

一直有一个令人恼火的建议,即

使用CLSID作为标识符,这种做法令人讨厌的短视。尝试在标签中嵌入消息类型怎么样???然后使用 PeadMessage 运行队列,直到找到明确针对特定队列的消息,并且消息类型可用于格式化消息属性,以便在第一次尝试时正确接收消息???

我知道这会产生一个复杂的代码集,但你宁愿不这样做吗?或者您是否实际上会尝试实现上述响应者的建议,他暗示如果您有一个由 200 个用户组成的系统,其中包含 200 种消息类型,他们应该创建 80,000 个队列来管理所有一对一的需求?有些人只是没有考虑清楚这些事情。

正如joocer在评论中指出的那样:对不同的消息类型使用不同的队列。

或者,您可以同意消息发送者的观点,即所有消息都将是 XML(任何不解析为 XML 的消息都将被拒绝)。然后还同意 XML 架构的一些基础知识:具有消息类型(和版本)的标头元素。

然后处理(通过序列化器自己)到内部类型。

当然,在许多情况下(反序列化没有真正的好处),只需根据需要读取 XML 的内容即可。