1

我正在编写一个小型 WCF 托管引擎,它将根据 .config 文件动态创建 ServiceHost。总体思路是允许我们在运行时删除现有服务以及添加新服务,而无需使所有服务脱机。

我遇到了一个问题单元测试,表明这可能不像听起来那么容易。对于任何给定的端点,似乎只有一个 ServiceHost 存在(即使一个服务的多个不同端点可能存在于单个 ServiceHost 中)。这通常不是问题,但是当需要重新配置服务时,关闭原始 ServiceHost 实际上并不会终止该端点地址的注册。尝试为同一服务(这意味着使用相同的端点)创建另一个 ServiceHost 失败,并出现以下异常:

System.InvalidOperationException: The ChannelDispatcher at 'net.pipe://localhost/' with contract(s) '"ITestService"' is unable to open its IChannelListener. --->
System.InvalidOperationException: A registration already exists for URI 'net.pipe://localhost/'.

我实际上在单元测试期间遇到了错误。测试将运行一个单元,该单元尽可能地完全关闭 ServiceHosts 和托管引擎。然后创建托管引擎的另一个实例,该实例尝试再次重新创建相同的 ServiceHosts 以进行不同的测试。第二次测试遇到上面的错误。我猜在调用 ServiceHost.Close() 时,它实际上并没有破坏服务主机......所以它仍然在内存中徘徊。我无法判断 GC 是否正在清理旧的服务主机……问题在最初发生后仍然存在并没有消失(据我所知,我已经能够确定……到目前为止,我已经等了大约 30 分钟。 )

我的 system.serviceModel 配置文件如下:

  <system.serviceModel>
    <services>
      <service name="Campus.Core.ServiceModel.TestServiceStub">
        <endpoint          
          address="net.pipe://localhost"          
          binding="netNamedPipeBinding"           
          contract="Campus.Core.ServiceModel.ITestService"
        />
      </service>
    </services>
  </system.serviceModel>
4

2 回答 2

3

为了提供这个问题的答案,以防其他人遇到问题。这个问题实际上有两个原因,如下:

1)在单元测试过程中,如果遇到异常,通常会在ServiceHost关闭之前就跳出正在测试的代码。这使 ServiceHost 绑定到特定端点。这导致执行同一段代码的所有后续测试都失败。当我使用 SubSpec 和 xUnit 进行 BDD 时,单个测试用例(在 BDD 术语中涉及)执行单个断言每个测试,单个测试用例可以包含多达十几个或更多断言。

2) 当心 MEX 端点。每个服务的 MEX 端点只能存在一次。最初,我创建了一个 http 和 net.tcp mex 端点。然而,这导致了一个问题,因为第二个启动的 MEX 端点实例引发了异常。一般来说,如果您使用 MEX 端点,HTTP 是最有用的协议,除非有一些物理基础设施问题阻止您这样做。

一般来说,在 ServiceHost 上调用 Close() 方法将完全解除绑定,从而允许之前绑定到其端点的任何地址再次可用。有时关闭可能需要一段时间,在极少数情况下,可能会引发异常。如果您使用 SubSpec 执行 BDD 并遵循每个测试单个断言的规则,则在一个测试中抛出的异常会阻止 ServiceHosts 关闭将导致所有后续测试失败。

于 2009-11-11T05:31:46.820 回答
1

一个答案是每次启动时将 Guid 附加到服务主机的 URL,并使用一种工厂方法来启动 ServiceHost 实例并返回客户端通道,以便客户端知道要使用哪个 url .

IDesign 的 InProcFactory 示例使用这种方法,因此您可以按原样使用它:

http://www.idesign.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=11

请注意,您必须在 IDesign 的网站上注册才能下载示例,他们会不定期地向您发送有关培训等的通知,但这并不过分。

于 2009-09-11T17:08:35.020 回答