10

我正在调查 Microsoft Message Queues 以进行进程间跨网络消息传递。但是当我收到一条消息时,我事先并不知道我得到的是什么类型的对象,所以代码

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

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

4

4 回答 4

12

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

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

来自TargetTypes

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

(重点补充)

于 2012-05-29T12:18:02.100 回答
3

您可能会考虑不在 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;
}
于 2012-05-29T12:18:09.663 回答
1

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

因此,这些参考资料都没有说队列要求只有一种消息类型。这将使 PeakMessage 和变体变得不必要甚至愚蠢。微软的文档含糊不清,但我在那里工作过,他们从不傻。

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

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

于 2013-10-21T23:04:07.597 回答
0

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

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

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

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

于 2012-05-29T12:19:11.640 回答