2012-08-16 68 views
17

我们在我们的WCF Web服务中将DTO用作数据合同。这些DTO的目的是仅公开与特定API方法相关的信息。如何组织和命名在WCF Web服务中用作数据合同的DTO

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

例如,请考虑下面这个简单的模型:

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属性被删除。

创建方法:用户无法指定标识CreatedOn性质,所以DTO是这样的:

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

更新方法:用户无法指定标识CreatedOn and CreatedBy属性,所以DTO看起来像这样:

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

获取方法:用户应该能够看到的一切的秩序,所以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之间共享,那么让这些类从一个公共基类中扩展是否有意义?如果是的话,那么“Get”DTO(OrderData)是否也可以从该类扩展?如果我们这样做,是否不会让这些DTO过于依赖对方?

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

  • 可以用“Data”或“DataObject”或“Dto”等后缀来表示所有的DTO吗?

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

更新:

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

+1

+1我认为这取决于个人偏好当我发现自己在这我倾向于去基类或将它们合并为一个,然后命名为'Upsert'。我会忽略任何后缀,如匈牙利语'dto'符号,因为您可以轻松识别类型,恕我直言,它更好地使用名称空间'Project.Data.DataObjects'而不是后缀,只是我的2美分 – 2012-08-16 02:02:26

+0

谢谢你的回应杰里米。我同意其中大部分是个人偏好,但我仍然希望有人能够验证这些问题和疑虑,并提出一些有关最佳实践和可能陷阱的论点。另外,如果我理解正确,Upsert应该表示“如果存在则更新,如果不存在则插入”。虽然这是一个有趣的想法,但这不是这些API的意图。这些API的使用者将具体了解何时插入或更新。 – 2012-08-16 02:29:45

回答

5

由于这是一个很多关于个人的喜好,我会做这个..

  1. 我不会创建一个共同的基类,因为这不会坚持L的固体。如果您担心DRY,那么您可以创建一个聚合。

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

  3. 我会后缀所有Dto,因为很多Dto类名与域类相同,所以它们会混淆,因为它们将以相同的方法存在。然后,你可以用DataContract(名称=“订单”,命名空间装饰你的DTO =“HTP:// YOURDOMAIN/..”。]这样,根据自己的喜好,他们会接触到外面的世界

我一直在使用相同的一般体系结构的多个项目,我一般使用AutoMapper将dtos映射到域,它对我来说非常好用

+0

我喜欢你的建议,特别是你提到的SOLID原则和共同的基础类。关于AutoMapper,我曾经使用它并喜欢它,但由于我们的对象并不是那么复杂,我们正在使用扩展方法进行转换。 – 2012-08-17 22:18:06