我开始设计一个现在很小的wcf服务总线,但随着我们的业务增长而增长,所以我担心一些问题并且也不会过多地关注YAGNI。这是一个电子商务平台。问题是我对于把东西放在哪里有太多的想法。我将给出一个场景来展示我的所有问题。
我们有一个电子商务网站,销售产品并最终交付产品。为此我们有一个PlaceOrder服务,除了其他参数之外,还需要一个Address对象,在这种情况下(我们的网站下订单)由City,Street和ZipCode组成。
我们还与仅使用我们平台销售产品的合作伙伴开展业务。他们负责交货。对于这种情况,我们有一个PlaceOrderForPartner服务,除了其他对象之外,还需要一个Address对象。但是,在此上下文中(合作伙伴下订单),Address对象由不同的信息组成,这些信息仅与合作伙伴下达的订单相关。
鉴于这种情况,我有几个问题:
1)如何在我的解决方案中的命名空间和文件夹中组织此DataContracts对象?我想过为每个上下文(合作伙伴,客户等)提供一个文件夹来保存服务和DataContracts。
所以我会
- MySolution.sln - Partner (folder) - PartnetService.svc - DataContracts (folder) - Address - Customer (folder) - Customer.svc - DataContracts (folder) - Address
使用这种方式,我将有一个命名空间来放置我所有特定于上下文的数据交换。
2)服务设计怎么样?我应该为每个可能放置的服务创建一个服务,并在其中订购和创建一个PlaceOrder方法,如下所示:
Partner.svc / PlaceOrder
Customer.svc / PlaceOrder
或使用PlaceOrderForPartner和PlaceInternalOrder创建订单服务,如下所示:
Order.svc / PlaceOrderForPartner
Order.svc / PlaceOrderForCustomer
3)假设我在上一个问题中选择了第一个选项,我该如何处理订单上的操作以及合作伙伴和客户的共同操作?
4)我应该将DataContracts和Service定义放在同一个程序集中吗?每个一个?一切都与服务实施?
5)如何为操作命名输入和输出消息?我应该使用实体本身还是使用OperationNameRequest和OperationNameResponse模板?
最重要的是,我的问题是:如何“组织”服务创建中涉及的数据交换和服务?
提前感谢您对此的任何想法!
答案 0 :(得分:10)
我喜欢这样构建我的WCF解决方案:
合同(类库)
包含所有服务,操作,故障和数据协定。可以在纯.NET-to-.NET场景中在服务器和客户端之间共享
服务实施(类库)
包含实现服务的代码,以及实现此目的所需的任何支持/帮助程序方法。没别了。
服务主机(可选 - 可以是Winforms,Console App,NT Service)
包含用于调试/测试的服务主机,或者也可能用于生产。
这基本上给了我服务器方面的东西。
在客户端:
客户端代理(类库)
我喜欢将我的客户端代理打包到一个单独的类库中,以便它们可以被多个实际的客户端应用程序重用。这可以使用svcutil或“添加服务引用”并手动调整生成的可怕的app.config,或者通过使用ClientBase<T>
或ChannelFactory<T>
构造手动实现客户端代理(共享契约程序集时)来完成
1-n个实际客户(任何类型的应用)
通常只会引用客户端代理程序集,或者也可能引用契约程序集(如果它正在共享)。这可以是ASP.NET,WPF,Winforms,控制台应用程序,其他服务 - 您可以命名。
这是受到Miguel Castro的Extreme WCF screen cast在DotNet Rocks电视上与Carl Franklin的启发 - 强烈推荐的屏幕演员!
答案 1 :(得分:1)
你在最高级别出错了。
它不应该是“PlaceOrder”服务,而是“OrderManager”。也许您想稍后添加更多服务功能 - 例如查询订单,取消订单,更改订单 - 谁知道。一般来说,我会保持“服务”(.svc)的数量很小并在那里添加方法。否则,你最终会在代码中使用它们的HUGH开销 - 没有任何实际好处。
为什么要将合作伙伴和客户分开?我相信通过15分钟的数据设计,您可以将内容分解为一个数据结构,这样您就只能拥有一项服务。如果不是......在一个接口上制作这两种方法,则按安全性限制。但我真的不喜欢两个程序。而是有两个地址字段 - “地址”和“PartnerInfo”,只能设置一个(其他必须为空),在逻辑中检查。
分成两个项目。接口,数据合同进入一个单独的项目(blabalbla.Api),以便客户可以实际获得DLL,如果他们想要 - 至少它使事情变得更容易,你可以依赖“共享类型”,不需要在内部生成包装器。允许更好的测试(因为子项目不会忘记重新生成包装器......这可能会在测试时导致错误。)
我总是把实现放到“blabla.Service”项目中。 Url将是子域中的“Services.blabla.com/”(或“api.blabla.com”,主要取决于心情,但最近我主要是为了api) - 将主要网站分离出来。