18

我们在 WCF Web 服务中使用 DTO 作为数据协定。这些 DTO 的目的是仅公开与特定 API 方法相关的信息。

我向你们寻求的是关于这里的最佳实践的一些建议。

例如,考虑以下简单模型:

class Order
{
    int CreatedBy { get; set; }
    DateTime CreatedOn { get; set; }
    string Description { get; set; }
    int Id { get; set; }
    string Name { get; set; }
}

假设我们的 API 允许消费者创建更新获取订单,我们创建了以下 DTO。为简单起见,删除了 DataMember 和 DataContract 属性。

Create方法:用户不能指定IdCreatedOn属性,因此 DTO 如下所示:

class CreateOrderData
{
    int CreatedBy { get; set; }
    string Description { get; set; }
    string Name { get; set; }
}

更新方法:用户不能指定IdCreatedOnCreatedBy属性,因此 DTO 如下所示:

class UpdateOrderData
{
    string Description { get; set; }
    string Name { get; set; }
}

Get方法:用户应该能够看到 Order 的所有内容,因此 DTO 如下所示:

class OrderData
{
    int CreatedBy { get; set; }
    DateTime CreatedOn { get; set; }
    string Description { get; set; }
    int Id { get; set; }
    string Name { get; set; }
}

所以这是我的问题:

  • 假设 Order 模型中有更多属性,并且其中许多属性在“创建”和“更新”DTO 之间共享,那么让这些类从公共基类扩展是否有意义?如果是,“获取”DTO(OrderData)是否也应该从该类扩展?如果我们这样做,是不是让这些 DTO 过于依赖彼此?

  • 如果“创建”和“更新”DTO 之间的所有属性都是通用的,我们还应该创建两个不同的 DTO 吗?如果是,为什么?如果不是,(现在这只是一个命名问题)应该调用什么“CreateOrUpdate”DTO 以便名称明显不同于“Get”DTO?

  • 是否可以在所有 DTO 后面加上“Data”或“DataObject”或“Dto”之类的东西?

  • 我们在正确的轨道上吗?如果没有,如何才能使这个设计更好?

更新:

我认为我不喜欢 DTO 中的继承,因为基类也将在 WSDL 中公开,并且客户端将能够看到它并实例化它,这对我来说似乎很脏(参见:WCF Serialization with object inherit?) . 如何在 DTO 中使用接口来强制执行公共属性而不是继承?由于 DTO 中不应该有任何行为,因此我们不会因为替换继承而损失太多。

4

1 回答 1

6

由于这与个人喜好有关,因此我会这样做..

  1. 我不会创建一个公共基类,因为它不会遵守 SOLID 中的 L。如果您担心 DRY,那么您可以创建一个聚合。

  2. 如果所有属性都是通用的,那么创建一个接收该对象的 Save 就很有意义,订单 Dto 类将具有一个关键属性,该属性将指示其是否存在订单。

  3. 我会用 Dto 作为后缀,因为很多 Dto 类名称与域类相同,它们会让人感到困惑,因为它们会一起存在于同一个方法中。然后你可以用 DataContract(Name="Order", Namespace="htp://yourdomain/.."] 装饰你的 Dtos。这样他们就会根据你自己的喜好暴露给外界。

我参与过多个使用相同通用架构的项目,我通常使用 AutoMapper 将 dto 映射到域。它对我很有用!

于 2012-08-16T18:48:57.757 回答