2014-04-08 53 views
4

我希望能夠在一個隊列上發送兩個不同的JSON消息。在C#中,我如何確定收到哪種類型的消息,以便可以將消息反序列化爲適當的對象?我應該使用消息頭還是創建另一個隊列?每個消息類型的隊列對我來說似乎過分。謝謝!如何在一個RabbitMQ隊列上告訴兩個JSON對象?

附加信息: 我有一個處理「運行」的Windows服務。一個運行ID由另一個系統分配,並且該ID被放入一個隊列中。我的服務提取身份證並開始工作。每次運行都會創建一個對象。現在,如果我想取消工作,我必須停止服務。但是,這停止了所有的工作。我想添加一個CancelRun類型的方法,但我需要的所有運行ID。所以,我可以使用完全相同的JSON(如此相同的類)。兩個隊列不會太可怕,但我認爲將這個類型或某種東西添加到自定義標題可能會很聰明。

回答

3

這是我一起去的。我喜歡這種技術,因爲我沒有將東西添加到不屬於模型的JSON中。

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

然後,在接收端,我這樣做(我養的一個自定義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); 

在亞洲其他項目:

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); 
} 
} 
+0

我不知道爲什麼沒有人標記這個正確的答案,它是最好的方式,保持消息體乾淨,並使用元數據。正確的答案對我來說。幹得好 – sacha

+0

@sacha謝謝!如果沒有其他的輸入,我不想接受我自己的答案。我很欣賞反饋! –

0

JSON並未說明它的序列化類型,除非序列化程序本身向JSON添加了一些信息。

您可以將某些結構添加到JSON中,以便能夠扣除該類型。

+0

由於該類型不在JSON中,因此會將類型添加到消息頭中是否合適? –

0

您可以將它們全部添加到數組中,然後基於類型進行反序列化,您將不得不手動添加類型屬性,或者可以創建對象IHaveType,然後在正在使用的對象中繼承它,但這太可怕了這樣做的方法。

ObjectType1 : HaveType 

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

的Json

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

添加由sphair建議運行時類型信息的工作,但我不喜歡這樣做,因爲你失去具有弱類型的便攜性價值。你也可以考慮使反序列化的C#對象足夠通用以處理所有的風味,然後從那裏分支。

+0

我也想過。我可以爲CancelRun添加一個布爾值,並且對於新的工作是假的,對於取消工作是正確的,但是對我來說這看起來有些不好。 –

1

如果訂單或接收和處理這些消息不是問題,我想建議爲每種類型使用單獨的隊列,對於兔子來說,處理大量隊列並不是問題。 如果沒有,訂單對您至關重要,您可以將標記放置在定義消息類型的消息標題中,但這會將您的業務邏輯與傳輸層綁定。如果您希望稍後在應用程序中更改傳輸層,則必須採用這部分代碼才能使其工作。相反,你可以爲隱藏內部內容的那些對象類型做出某種包裝,看起來是相同的,並且可以按其包含的類型進行淡化。

+0

我確實考慮過單獨的隊列,但那時對我來說似乎過分了。我真的很喜歡你的一個包裝類的想法,可以找出正確的對象來生成。聽起來有點像工廠模式。 –

+0

處理兔子的多個隊列在性能方面不是問題,直到它被限制而不是持續增長。 – gelmanet

+1

我並不擔心性能問題。每次我定義一個新的消息類時,我都不想養成新隊列的習慣。 –

相關問題