2013-05-10 57 views
1

我正在學習有關MsmqIntegrationBinding。到目前爲止,我所見過的所有樣本和指南都涵蓋了一個數據合同只有一個操作的場景。我試圖添加另一份合同,並且服務已成功啓動。但我無法弄清楚如何達到第二個操作。這種綁定有可能實現嗎?MsmqIntegrationBinding是否支持多種服務操作

[ServiceContract] 
[ServiceKnownType(typeof(Data1))] 
[ServiceKnownType(typeof(Data2))] 
public interface ISampleService 
{ 
    [OperationContract(IsOneWay = true, Action = "*")] 
    void Operation1(MsmqMessage<Data1> msg); 

    [OperationContract(IsOneWay = true)] 
    void Operation2(MsmqMessage<Data2> msg); 
} 

public class SampleService : ISampleService 
{ 
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 
    public void Operation1(MsmqMessage<Data1> msg) 
    { 
     var data = msg.Body; 
    } 

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 
    public void Operation2(MsmqMessage<Data2> msg) 
    { 
     var data = msg.Body; 
    } 
} 

調用代碼

var queue = new MessageQueue(@".\private$\samplequeue"); 
var body = new Data1() { Data = "some data" }; 
var message = new Message(body); 
message.Label = "some label"; 
queue.Send(body, MessageQueueTransactionType.Single); 

這將觸發其具有操作設置爲 「*」 的Operation1。

+0

你的調用代碼是什麼樣的? – 2013-05-12 07:08:42

+0

我添加了調用代碼。這很簡單。只是普通的MSMQ消息。 – StanislawSwierc 2013-05-13 09:28:43

+0

如果您刪除了Action = *會發生什麼? – 2013-05-14 10:10:56

回答

1

這是一個非常有趣的問題。

Action OperationContractAttribute通常由WCF堆棧用來填充WS-Addressing肥皂標題。它的使用顯然被排隊的綁定以某種方式重寫。

這可能是有WCF的無證功能,它允許對基於該動作的操作MSMQ消息頭的一些映射屬性像個過濾器,但是如果我不知道是什麼形式,它會採取。

我認爲最簡單的解釋是:不,這是不可能的,原因是msmqIntegrationBinding正是它所說的:它是關於互操作性的功能。

由於您不得不使用MsmqMessage包裝器調用操作,它使得這種綁定在語義上是一維的,這有助於我的理論,即它打算包裝單個端點操作以支持與傳統COM的互操作, ActiveX客戶端。

無論如何,沒有法律說綁定必須支持多個操作,就像某些綁定不支持回調,而某些綁定不支持單向操作。

欣賞這並不直接回答你的問題。

+0

看來,MsmqIntegrationBinding功能非常有限。我找到了一個教程,介紹瞭如何在WCF中擴展操作選擇,但我放棄了它。 http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/10/wcf-extensibility-operation-selectors.aspx – StanislawSwierc 2013-05-18 18:52:05

+0

感謝您的鏈接 - 真的很有趣。看起來很難。 – 2013-05-20 07:46:12

2

不確定這是答案,我沒有要求評論的50條信譽。

從這個答案中獲取靈感:https://stackoverflow.com/a/33154517/1095296我們正在做以下工作。

[ServiceContract] 
public interface IMSMQueueHandler 
{ 
    [OperationContract(IsOneWay = true, Action = "*")] 
    void Handle(MsmqMessage<object> message); 
} 

然後我們在類的構造函數包裹服務主機

public MSMQueueServiceHost(IMSMQConfig msmqConfig, IMSMQueueHandler handler) 
    { 
     _hostService = new ServiceHost(handler); 

     AddHostServiceEndPoint(msmqConfig); 

     _hostService.Open(); 
    } 

    private void AddHostServiceEndPoint(IMSMQConfig msmqConfig) 
    { 
     ServiceMetadataBehavior smb = new ServiceMetadataBehavior { HttpGetEnabled = false }; 
     _hostService.Description.Behaviors.Add(smb); 

     MsmqIntegrationBinding binding = new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None); 
     binding.SerializationFormat = MsmqMessageSerializationFormat.Stream; 
     binding.ReceiveErrorHandling = ReceiveErrorHandling.Move; 

     ServiceEndpoint endpoint = _hostService.AddServiceEndpoint(
      typeof(IMSMQueueHandler), 
      binding, 
      string.Format("msmq.formatname:DIRECT=OS:{0}", msmqConfig.MsmqPath)); 

     // enforce ServiceBehaviours and OperationBehaviours so we dont have to decorate all the handlers 
     _hostService.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single; 
     _hostService.Description.Behaviors.Find<ServiceBehaviorAttribute>().ConcurrencyMode = ConcurrencyMode.Single; 

     AddKnownTypes(endpoint); 
    } 

    private static void AddKnownTypes(ServiceEndpoint endpoint) 
    { 
     foreach(OperationDescription operation in endpoint.Contract.Operations) 
     { 
      operation.KnownTypes.Add(typeof(XElement)); 
      operation.Behaviors.Find<OperationBehaviorAttribute>().TransactionScopeRequired = true; 
      operation.Behaviors.Find<OperationBehaviorAttribute>().TransactionAutoComplete = true; 
     } 
    } 

這裏代碼的關鍵線路,使其工作有:

[OperationContract(IsOneWay = true, Action = "*")] 
void Handle(MsmqMessage<object> message); 

binding.SerializationFormat = MsmqMessageSerializationFormat.Stream; 

operation.KnownTypes.Add(typeof(XElement)); 

的原因流格式是我們看到包裹在大括號中的消息體中的XML(氣味像JSON,但我們沒有看到爲什麼)。

最後,我不知道,因爲它不使用WCF DataContract,這是一個答案的原因內置的WCF序列化,我們通過包含以下的方法來構造一個句柄:

public void Handle(MsmqMessage<object> message) 
    { 
     object msmqType = Serializer.Deserialize(message.Body); 

     _bus.Publish(msmqType); 
    } 

如果不明顯,我們使用XML序列化消息。