对象和Web服务依赖项

时间:2013-06-06 11:12:44

标签: c# wcf dependency-injection idisposable

我有一个关于实现依赖注入模式的问题。我有一个类需要访问Web服务。根据这种模式,我不应该让我的类实例化服务,因为这会导致与它的强烈依赖。这导致我创建一个构造我的类的工厂类,并在其构造函数中传递它所需的正确服务,即依赖项。

令我感到不安的是,我正在将Web服务客户端的实例传递给我的对象,但这不会让服务保持打开状态吗?

我应该通过整个客户端而不是只接口吗?这样我可以实现IDisposable并关闭与服务的连接?

提前致谢。 请随意更正任何术语,不要造成混淆。

例如:

public class ProductService
{
    private IProductService client;

    public ProductService(IProductService client)
    {
        this.client = client;
    }

    public void DoIt()
    {
        client.MyWebMethod();
    }
}

public class Factory
{
    public static T Create<T>() where T : class
    {
        T item = null;

        if (typeof(T) == typeof(ProductService))
        {
            item = new CustomerService(**new ProducttServiceClient()**) as T;
        }
        return item;
    }
}

2 个答案:

答案 0 :(得分:0)

是的,如果你自己new ProducttServiceClient()创建实例,那么你/工厂需要处理它。这就是像Unity,Castle Windsor这样的DI容器可以帮助你并释放/处理它的地方。

假设我们正在讨论生成的服务客户端ProducttServiceClient - ClientBase的子类,请注意,如果您处置客户端,它将尝试关闭已打开但未中止的通道 - 这可能会导致异常。See this link for details

如果您只是传入已打开的频道(System.ServiceModel.ClientBase.CreateChannel()),那么您可以关闭/中止它并再次重复使用该客户端。

答案 1 :(得分:0)

是的,如果您的工厂类创建服务客户端实例,它也应该负责关闭它。但是你想要实现什么(除了尝试依赖注入和工厂模式)?在这种情况下,我认为工厂模式不会给你太多。

如果您不希望客户端每次要调用服务操作时都创建和关闭代理,我建议在ICommunicationObject上创建一个负责执行工作然后关闭代理的扩展方法。然后你只需要实现一次(在一个地方!)处理你的客户端的逻辑。

扩展程序可能如下所示:

public static TResult Using<T, TResult>(this T client, Func<T, TResult> work) where T : ICommunicationObject
{
    TResult res = default(TResult);
    try
    {
        res = work(client);
        client.Close();
    }
    catch (CommunicationException)
    {
        client.Abort();
            throw;
    } // ... more catch cases might go here... 
    finally
    {
        if (client.State != CommunicationState.Closed)
            client.Abort();
    }

    return res;
}

您的客户端会调用这样的方法:

using TheNameOfYourNamespaceDefiningTheExtension

return new ServiceClient().Using(client => client.MethodName(request));