WCF和依赖注入

时间:2012-01-13 17:20:01

标签: .net wcf unit-testing dependency-injection

我有一组使用依赖注入实现的WCF服务用于测试目的。

基本上这些服务有时会相互调用,所以在我的单元测试中,我可以使用接口模拟存储库和WCF服务,并将它们作为服务构造函数中的组件注入。

这很棒,因为我可以在没有任何依赖的情况下正确测试这些服务。

我还实现了自己的代理,以避免使用Visual Studio服务引用(这会产生大量垃圾),所以我使用的是ChannelFactory CreateChannel方法。

我有点担心现场环境会发生什么。

我的WCF服务调用另一个WCF服务只会在构造函数中注入此外部组件的一个实例,因此我一旦使用就无法处置此对象。

这是否会造成麻烦? 垃圾收集者会照顾它吗? 连接是否仍然开放? 这种方法有误吗?

非常感谢。

2 个答案:

答案 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>装饰器以应用交叉问题,例如消息级别的安全性 - 添加标题等。