【发布时间】:2015-10-13 12:08:33
【问题描述】:
我们开发了一个 WCF Web 服务,其合同类似于以下内容:
[ServiceContract(Namespace = "XXX")]
public interface ISynchronization
{
[OperationContract(IsOneWay = true)]
void ProcessEntities(List<BaseEntity> entities);
}
通过在配置文件的datacontractserializer 下使用BaseEntity 的knowntypes 配置,它工作得很好并且很容易扩展。
现在需要使用NServiceBus 的可靠消息传递,我需要提出适当的消息格式,能够以通用方式传输实体。
我是NServiceBus 的新手,但据我了解,默认的 NSB 序列化程序不会关心多态性,我被困在每个实体的命令场景中。
上面提到的不是任何类型的轮子改造,必须有一个优雅的解决方案。
使用 DataContractSerializer 代替 NSB 的原生有哪些可能的缺点?
EDIT(继承测试作为对 Ramon 的回答)
我使用了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,其中的实体列表填充了Employee 和Organization:
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)
【问题讨论】:
-
不完全清楚为什么您想要拥有如此灵活的消息。您的界面表明您正在消息传递之上构建自己的“复制”。为什么没有每个实体的消息?为什么要将它们批处理在一条消息中?单个消息具有大小限制。
-
我正在处理相同类型实体的平面列表(列表大小将根据性能测试的结果来定义)。明天,如果我需要添加一个额外的实体,我将只为
BaseEntity注册相应的knownType,DCS 会处理这个问题。其余部分通过 IoC 容器完成,该容器初始化存储库,然后映射到实体类型。您是否会说每个实体的消息是更好的选择(答案中SyncronizeCommand中的单个 BaseEntity 属性),为什么? -
如果所有新类型的处理完全相同,那么这可以工作,但如果处理不同,那么最好将它们放在不同的消息类型中。此外,我不会在消息中进行批处理,除非它是因为事务边界(所有项目都必须成功,否则不会)。如果这是一种数据复制,那么这是一种反模式。不要在消息传递之上构建复制。为该选项或其他类似的低级选项使用 SQL 服务复制。
-
这是一个集成。为一个系统提供来自另一个系统的数据。可以按需或按计划进行。
-
这是与外部系统的集成吗?是不是可以使用复合 UI 的概念来仅将数据集成到 UI 中,而不将该数据的副本保存在另一个系统的数据库中?
标签: .net wcf nservicebus