1

虽然我正在尝试学习 WCF,而且看起来很简单,但我遇到了一个奇怪的情况……至少在我看来这很奇怪。

为什么 ServiceHost ctor 采用具体类,而 AddServiceEndpoint 采用接口,反之则不然?从 OOP 的角度来看,后者似乎更合乎逻辑。

考虑以下:

    [ServiceContract]
    interface IVocalAnimal
    {
        [OperationContract]
        string MakeSound();
    }
  ...      
  public class Dog : IVocalAnimal
  {
     public string MakeSound()
     {
        return("Woof!");
     }
  }
 ...
 public class Cat : IVocalAnimal
  {
     public string MakeSound()
     {
        return("Meeooow!");
     }
  }

所以现在我们要创建一个“AnimalSound”服务,您可以通过 /AnimalSoundService/Dog 或 /AnimalSoundService/Cat 连接来获取狗或猫的声音

...
Uri baseAddress = new Uri("net.pipe://localhost/AnimalSoundService");
ServiceHost serviceHost = new ServiceHost(typeof(IVocalAnimal), baseAddress);
serviceHost.AddServiceEndpoint(typeof(Dog), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "Dog");
serviceHost.AddServiceEndpoint(typeof(Cat), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "Cat");
...

但是上面的代码由于某些原因无法编译,因为我不太明白,ServiceHost ctor 想要具体的类(所以是 Dog 或 Cat),而 EndPoint 想要接口。

那么它不是反之亦然的原因是什么,因为在我看来,更细粒度的端点支持特定的实现更自然(因此您可以针对每个端点地址命中合同的特定实现),而更通用的 ServiceHost 应该是一个接受接口?

顺便说一句,我不是迂腐……我只是诚实地试图理解,因为我确信是我在这里错过了一些东西。

4

3 回答 3

2

创建 ServiceHost 时,您正在创建实际的服务,因此它必须是具体的。

另一方面,您的端点就是您的客户所看到的。您不一定希望您的客户知道您的实现——他们应该只获得接口定义。

正如您所说,端点确实支持特定的实现:无论您在创建 ServiceHost 时使用哪个。端点的目的不是提供多个实现,而是提供多个协议/绑定来访问单个实现。

如果您想要不同的 Dog 和 Cat 服务,我相信您需要两个 ServiceHost,每个都有一个 NetNamedPipeBinding 端点。

于 2009-06-01T05:01:32.643 回答
2

我明白你在想什么。从 OOP 的角度来看,这是有道理的,但这不是服务的角度。服务是一组操作。该组操作在合同中定义。您可以使用类来为服务契约建模,但大多数使用接口,因为接口是一种更直接的模型。MSDN 对这些概念进行了很好的讨论

记住,你不认识我,我也不认识你。我们交换消息,而不是对象。我不想要你的猫和狗。除非我们事先达成协议,否则我不知道如何处理你给我的猫或狗。你告诉我我能做什么,我会调用你的方法来做到这一点。这是一篇关于内部数据与外部数据的好文章。

于 2009-06-01T05:24:04.517 回答
1

我不得不对其他答案有点不同意。虽然它们在某种程度上在技术上是正确的,但我认为最重要的原因是它与隐藏实现或使用类与接口来定义服务契约无关。

如果您考虑到单个服务实现可以公开多个端点的事实,那么为什么会这样就更明显了。如您所知,每个端点可能会或可能不会公开不同的合约,并且每个端点都可以在不同的绑定上公开。

例如,您可能有一项服务公开了一个通过 MSMQ 的单向契约和一个通过 HTTP 的双向契约。或者,它可能在一个 URL 上公开 JSON 合约,在另一个 URL 上公开 XML 合约。

于 2009-06-01T13:25:55.903 回答