我有一组使用依赖注入实现的WCF服务用于测试目的。
基本上这些服务有时会相互调用,所以在我的单元测试中,我可以使用接口模拟存储库和WCF服务,并将它们作为服务构造函数中的组件注入。
这很棒,因为我可以在没有任何依赖的情况下正确测试这些服务。
我还实现了自己的代理,以避免使用Visual Studio服务引用(这会产生大量垃圾),所以我使用的是ChannelFactory CreateChannel方法。
我有点担心现场环境会发生什么。
我的WCF服务调用另一个WCF服务只会在构造函数中注入此外部组件的一个实例,因此我一旦使用就无法处置此对象。
这是否会造成麻烦? 垃圾收集者会照顾它吗? 连接是否仍然开放? 这种方法有误吗?
非常感谢。
答案 0 :(得分:2)
当您调用CreateChannel方法时,ChannelFactory会创建一个通道对象。此通道对象实际上具有连接。
完成频道后,您应该通过调用IClientChannel.Close方法将其关闭。这应该导致任何底层网络连接被关闭。请注意,在某些情况下,调用Close方法可能会导致CommunicationObjectFaultedException异常,即使您首先验证您的频道未处于Faulted
状态。
您可以在code example of this MSDN documentation page中看到在wcfClientChannel对象上调用Close方法。
答案 1 :(得分:0)
是的,你应该关闭你打开的频道。您尚未指定实际使用渠道工厂的人员来打开渠道。无论是谁接到一个打开通道来工厂都有责任关闭它,因为这是唯一知道什么时候允许这样做的地方。
通常,您应该打开频道,拨打电话,然后立即将其关闭以释放与池的连接。 ChannelFactory<T>
已针对此进行了优化,并且在实际情况下将重复使用可用的连接,并且只处理合同等一次。
鉴于这些要点,到目前为止我最喜欢的是另一个抽象来明确定义这些open-invoke-close语义。我将IChannelInvoker<T>
称为Execute
方法。我现在的版本只是异步,但为简单起见,这是同步版本的样子:
public interface IChannelInvoker<TChannel>
{
/// <summary>
/// Executes a method within the context of an open channel
/// </summary>
TResult Execute<TResult>(Func<TChannel, TResult> method);
}
实现的Execute
方法使用ChannelFactory
打开通道,调用委托,关闭通道并返回结果。我把工厂注入那里并在应用程序的生命周期内保持不变。
现在在服务A中,您注入T
而不是注入频道IChannelInvoker<T>
。例如:
public class ServiceA : IServiceA
{
private readonly IChannelInvoker<IServiceB> _b;
public ServiceA(IChannelInvoker<IServiceB> b)
{
_b = b;
}
public void SomeOperationA()
{
_b.Execute(channel => channel.SomeOperationB());
}
}
调用程序也是可组合的,因此您可以添加其他IChannelInvoker<T>
装饰器以应用交叉问题,例如消息级别的安全性 - 添加标题等。