如何在一个RabbitMQ队列中区分两个JSON对象?

[英]How can I tell two JSON objects apart on one RabbitMQ queue?


I want to be able to send two different JSON messages on one queue. How do I, in C#, determine what type of message was received so that I can deserialize the message to the proper object? Should I use a message header or create another queue? A queue per message type seems excessive to me. Thanks!

我希望能够在一个队列上发送两个不同的JSON消息。我如何在C#中确定收到的消息类型,以便我可以将消息反序列化为正确的对象?我应该使用邮件头还是创建另一个队列?每种消息类型的队列对我来说似乎太过分了。谢谢!

Extra Details: I have a Windows service that processes "runs". A run ID is assigned by another system and the ID is dropped on a queue. My service picks up the ID and starts work. An object is created for each run. Right now, if I want to cancel work, I have to stop the service. But, that stops all work. I wanted to add a CancelRun type method, but all I need to the run ID. So, I could use the exact same JSON (so same class). Two queues wouldn't be horrible, but I thought it might be clever to add the type or something to a custom header.

额外细节:我有一个处理“运行”的Windows服务。运行ID由另一个系统分配,ID被删除在队列中。我的服务拿起ID并开始工作。为每次运行创建一个对象。现在,如果我想取消工作,我必须停止服务。但是,这会阻止所有工作。我想添加一个CancelRun类型的方法,但我只需要运行ID。所以,我可以使用完全相同的JSON(所以相同的类)。两个队列不会很糟糕,但我认为将类型或类型添加到自定义标题可能更聪明。

5 个解决方案

#1


3  

Here's what I went with. I like this technique because I'm not adding stuff to the JSON that isn't part of the model.

这就是我的用途。我喜欢这种技术,因为我没有向不属于模型的JSON添加内容。

IBasicProperties props = model.CreateBasicProperties();
props.Headers = new Dictionary<string, object>();
props.Headers.Add("RequestType", "CancelRunRequest");

Then, on the receiving side, I do this (I'm raising an event with a custom EventArg obj):

然后,在接收方,我这样做(我正在使用自定义EventArg obj引发一个事件):

// Raise message received event
var args = new MessageReceivedArgs();
args.CorrelationId = response.BasicProperties.CorrelationId;
args.Message = Encoding.UTF8.GetString(response.Body);
args.Exchange = response.Exchange;
args.RoutingKey = response.RoutingKey;

if (response.BasicProperties.Headers != null && response.BasicProperties.Headers.ContainsKey("RequestType"))
{
args.RequestType = Encoding.UTF8.GetString((byte[])response.BasicProperties.Headers["RequestType"]);
}

MessageReceived(this, args);
model.BasicAck(response.DeliveryTag, false);

Elsewhere in the project:

在项目的其他地方:

private void NewRunIdReceived(object p, MessageReceivedArgs e)
{

if(e.RequestType.ToUpper() == "CANCELRUNREQUEST")
{
    // This is a cancellation request
    CancelRun(e);
}
else
{
    // Default to startrun request for backwards compatibility.
    StartRun(e);
}
}

#2


1  

If an order or receiving and processing of these messages is not an issue I would like to suggest using separate queues for each type, it's not a problem for rabbit to handle tons of queues. If not, the order is crucial for you, you can put marker in header of the message defining it's type, however this will bind your Business Logic with transportation layer. In case you will want to change the transportation layer later in your application, you will have to adopt this section of code to keep it work. Instead of this you can make some sort of wrapper for both of those object types which hides the internal content, looks the same and can desalinize itself in type it contains.

如果订单或接收和处理这些消息不是问题,我建议为每种类型使用单独的队列,兔子处理大量队列不是问题。如果没有,订单对您来说至关重要,您可以将标记放在定义其类型的消息的标题中,但这会将您的业务逻辑与传输层绑定。如果您希望稍后在应用程序中更改传输层,则必须采用此部分代码才能使其正常工作。除此之外,您可以为这两种隐藏内部内容的对象类型制作某种包装,看起来相同,并且可以在其包含的类型中对自身进行脱盐。

#3


0  

Adding runtime type information as suggested by sphair works, but I dislike doing that since you loose the portability value of having a weak type. You might also consider having the deserialized C# object be generic enough to handle all the flavors, and then branch from there.

按照sphair的建议添加运行时类型信息,但我不喜欢这样做,因为你失去了弱类型的可移植性值。您可能还会考虑让反序列化的C#对象足够通用以处理所有风格,然后从那里进行分支。

#4


0  

You can add all of them into array and then deserialise based on type, you will have to add type property manually, or you could create Object IHaveType and then inherit from it in objects that are being used, but that's a horrible way to do this.

您可以将所有这些添加到数组中,然后根据类型进行反序列化,您必须手动添加type属性,或者您可以创建Object IHaveType,然后在正在使用的对象中继承它,但这是一种可怕的方法来执行此操作。

ObjectType1 : HaveType 

public class HaveType { public string Type { get { this.GetType(); }}}

Json

[{Type: 'ObjectType1', ...[other object stuff]},{Type : 'ObjectType2',...}]

#5


0  

JSON does not say what a type it was serialized from, unless the serializer itself adds some information to the JSON.

除非序列化程序本身向JSON添加了一些信息,否则JSON没有说明它是从哪个类型序列化的。

You could add some structure to the JSON so you are able to deduct the type.

您可以向JSON添加一些结构,以便您可以扣除类型。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/04/08/2fb46a607aed478e173c47a4cc1f62a3.html



 
  © 2014-2022 ITdaan.com 联系我们: