不确定这是一个答案,我没有必要的 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 序列化。