具有基本类型属性的 NServiceBus 消息

NServiceBus messages with properties of base type

我们开发了一个 WCF web 服务,其合同类似于以下内容:

[ServiceContract(Namespace = "XXX")]
public interface ISynchronization
{
    [OperationContract(IsOneWay = true)]
    void ProcessEntities(List<BaseEntity> entities);
}

它确实工作得很好,并且很容易通过在配置文件中的 datacontractserializer 下为 BaseEntity 使用 knowntypes 配置来扩展。

现在需要使用 NServiceBus 的可靠消息传递,我需要提出适当的消息格式,能够以通用方式传输实体。

我是 NServiceBus 的新手,但据我了解,默认的 NSB 序列化程序不会关心多态性,我被每个实体的命令所困。

上面提到的不是任何一种轮子改造,必须有一个优雅的解决方案。

使用 DataContractSerializer 而不是 NSB 的本机可能有哪些缺点?


编辑(继承测试作为对拉蒙回答的回复)

我使用了其中一个 NSB test projects 并更改了 CancelOrder,如下所示:

public class CancelOrder : IMessage
{
    public int OrderId { get; set; }
    public List<EntityBase> Entities { get; set; }
}

[KnownType(typeof(Employee))]
[KnownType(typeof(Organization))] //Serialization fails otherwise
public class EntityBase
{
    public virtual string Name { get; set; }
}

public class Employee : EntityBase {
    public override string Name {get{ return "Employee"; }}
    public string EmployeeProperty {get{ return "Employee Property Value"; }}
}

public class Organization : EntityBase
{
    public override string Name {get{ return "Organization"; }}
    public string OrganizationProperty {get { return "Organization Property Value"; }}
}

EntityBase(不是抽象的——这也阻止了序列化)有一个虚拟的 属性 Name 以便于测试。

测试客户端正在发送一个 CancelOrder 实体列表填充了 EmployeeOrganization:

 var message = new CancelOrder
               {
                 OrderId = orderId++,
                 Entities = new List<EntityBase>
                 {
                   new Employee(), 
                   new Organization()
                 }
               };

 var returnCode = client.Process(message);

一旦传送到服务器,它们就不再是 EntityBase 类型 (message.Entities[0] as Employee == null)

您的界面可以转换为以下消息:

public class SynchronizeCommand : IMessage
{
    public int OrderId { get; set; }
    public List<EntityBase> Entities { get; set; }
}

[KnownType(typeof(Employee))] // Required for WCF, not the Json serializer
[KnownType(typeof(Organization))]
public class EntityBase
{
    public virtual string Name { get; set; }
}

public class Employee : EntityBase {
    public override string Name {get{ return "Employee"; }}
    public string EmployeeProperty {get{ return "Employee Property Value"; }}
}

public class Organization : EntityBase
{
    public override string Name {get{ return "Organization"; }}
    public string OrganizationProperty {get { return "Organization Property Value"; }}
}

NServiceBus XML 序列化程序无法对此进行序列化,但 Json 序列化程序可以。

您提到的多态性限制是关于消息类型而不是它的属性。

如果您想要触发处理程序类型的多态行为,那么您不能对 classes 使用多重继承。只允许接口,因为它们是唯一允许多重继承的类型。

数据协定序列化器缺点

  • 无法序列化接口,需要 class
  • 您需要在所有端点上使用 DataContractSerializer
  • NServiceBus 序列化程序不够灵活,无法保持消息契约的简单性
  • XML 可读性较差

数据契约序列化程序的优点

  • 更适合集成目的
  • 支持复杂数据,例如具有循环引用的图表