设计WCF数据契约和操作

4
我开始设计一个WCF服务总线,目前规模较小,但随着业务的增长会不断扩大,因此我担心一些增长问题,同时也尽量避免过度设计。这是一个电子商务平台。问题在于我对该把什么放在哪里有太多疑虑了。我将举一个场景来说明我的所有问题。
我们有一个电子商务网站,销售产品并最终交付产品。为此,我们有一个PlaceOrder服务,其中包括其他参数,期望Address对象。在这种情况下(我们的网站下订单),Address对象由City、Street和ZipCode组成。
我们还与使用我们平台仅销售产品的合作伙伴合作。他们负责交付。为此,我们有一个PlaceOrderForPartner服务,其中包括其他对象,期望Address对象。然而,在这种情况下(合作伙伴下订单),Address对象由不同的信息组成,这些信息仅与合作伙伴下订单有关。
在这种情况下,我有几个问题:
1)如何在我的解决方案中组织这些DataContracts对象的名称空间和文件夹?我考虑每个上下文(合作伙伴、客户等)都有一个文件夹,以保留服务和DataContracts。
因此,我会有
- MySolution.sln - Partner(文件夹) - PartnetService.svc - DataContracts(文件夹) - Address - Customer(文件夹) - Customer.svc - DataContracts(文件夹) - Address
使用这种方式,我将有一个名称空间来放置所有特定于上下文的数据合同。
2)服务设计怎么样?我应该为每个可能下订单的人创建一个服务,并在其中创建一个PlaceOrder方法,如下所示:
Partner.svc/PlaceOrder Customer.svc/PlaceOrder 还是创建一个Order服务,包括PlaceOrderForPartner和PlaceInternalOrder,如下所示:
Order.svc/PlaceOrderForPartner Order.svc/PlaceOrderForCustomer 3)假设我选择了最后一个问题的第一个选项,那么我应该怎么处理在合作伙伴和客户中都进行的与订单相关的操作?
4)应该将DataContracts和Service定义放在同一程序集中吗?每个都需要吗?所有内容都包括服务实现?
5)如何为操作命名输入和输出消息?应该使用实体本身还是采用OperationNameRequest和OperationNameResponse模板?
总之,我的主要问题是:如何“组织”涉及服务创建的DataContracts和服务?
谢谢您提前对此的任何想法!
2个回答

10
除了TomTom提到的,我也想在这里加入我的两分钱意见:
我喜欢按照以下结构来组织我的WCF解决方案: 契约(类库) 包含所有服务、操作、故障和数据契约。在纯.NET-to-.NET场景中可以在服务器和客户端之间共享。 服务实现(类库) 包含实现服务所需的代码以及任何支持/辅助方法。除此之外没有其他内容。 服务主机(可选 - 可以是Winforms、控制台应用程序、NT服务) 包含服务主机以进行调试/测试,或者可能也包含用于生产的服务主机。
这基本上给了我服务器端的东西。
在客户端方面: 客户端代理(类库) 我喜欢将客户端代理打包到单独的类库中,以便它们可以被多个实际客户端应用程序重复使用。可以使用svcutil或"Add Service Reference"并手动调整生成的可怕app.config,或通过对客户端代理进行手动实现(当共享契约程序集时)使用ClientBase<T>或ChannelFactory<T>构造。 1-n个实际客户端(任何类型的应用程序) 通常只会引用客户端代理程序集,或者如果共享则可能也会引用契约程序集。可以是ASP.NET、WPF、Winforms、控制台应用程序、其他服务等等。
这样,我就有了一个漂亮干净的布局,一遍又一遍地使用它,并且我真的认为这使我的代码更加清洁和易于维护。
这受到Miguel Castro在DotNet Rocks TV上与Carl Franklin合作的Extreme WCF screen cast的启发 - 强烈推荐此屏幕展示!

1
你从最高层面开始错了。
  • 应该不是“PlaceOrder”服务,而是“OrderManager”。也许你想添加更多的服务功能——比如查询订单、取消订单、修改订单——谁知道呢。总的来说,我会保持“服务”(.svc)的数量较少,并在其中添加方法。否则,在代码中使用它们会导致巨大的开销,而没有任何真正的好处。

  • 为什么要区分合作伙伴和客户?我相信只需要15分钟的数据设计,就可以将事物分解为一个数据结构,这样你就可以只有一个服务了。如果不行……那就在一个接口上做两个方法,通过安全性进行限制。但我真的不希望有两个程序。还不如有两个地址字段——“地址”和“合作伙伴信息”,只能设置一个(另一个必须为空),在逻辑中进行检查。

  • 拆分成两个项目。接口、数据契约放在一个单独的项目中(blabalbla.Api),这样客户实际上可以获取DLL——至少对你来说,这样做会更容易,你可以依赖于“共享类型”,无需在内部生成包装器。允许更好的测试(因为子项目不会忘记重新生成包装器……这可能会在测试时导致错误)。

  • 我总是将实现放在一个“blabla.Service”项目中。URL将是“Services.blabla.com/”在子域中(或“api.blabla.com”,主要取决于心情,但最近我大多数时候都选择api)——将事物分离出来,与主网站分开。


我对最新的两个回答感到满意,但前两个回答不太满意。我阅读了一些指南(包括微软和Juval Lowy的指南),其中指出一个服务中不应该有超过12个操作,并且应该将它们与上下文相关联。不将数据契约分离的另一个问题是,我可能会得到所有服务具有相同签名但从不同字段读取的情况,这并不是很语义化。 - tucaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接