如何在一個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 联系我们: