1

我正在学习 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);

这将触发将 Action 设置为“*”的 Operation1。

4

2 回答 2

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));

Stream 格式的原因是我们看到消息正文中的 XML 用大括号括起来(闻起来像 JSON,但我们看不出原因)。

最后,我不确定这是不是一个答案,因为它没有使用 WCF DataContract 和内置的 WCF 序列化,我们将包含以下方法的处理程序传递给构造函数:

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

        _bus.Publish(msmqType);
    }

如果不是很明显,我们正在对消息使用 XML 序列化。

于 2016-09-16T11:04:01.013 回答
1

这是一个非常有趣的问题。

WCF 堆栈通常使用 Action OperationContractAttribute 来填充 WS-Addressing soap 标头。它的使用显然被排队的绑定以某种方式覆盖。

WCF 可能有一个未记录的功能,它允许将 msmq 消息头映射到基于 Action 属性的操作,就像过滤器一样,但如果有,我不知道它会采用什么形式。

我认为最简单的解释是:不,这是不可能的,原因是 msmqIntegrationBinding 正是它在锡上所说的:它是关于互操作的功能。

因为您被迫使用 MsmqMessage 包装器调用该操作,所以这种绑定在语义上是一维的,这使我的理论是,它旨在包装单个端点操作以支持与旧 COM 和 ActiveX 客户端的互操作。

无论如何,没有法律规定绑定必须支持多个操作,就像某些绑定不支持回调,而某些其他绑定只支持单向操作一样。

欣赏这并不能直接回答您的问题。

于 2013-05-15T12:33:47.283 回答