1

我有一个关于实现依赖注入模式的问题。我有一个需要访问 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;
    }
}
4

2 回答 2

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));
于 2013-06-07T09:04:08.523 回答
0

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

假设我们正在讨论生成的服务客户端 ProducttServiceClient - ClientBase 的子类,请注意,如果您处理客户端,它将尝试关闭已打开且未中止的通道 - 这可能导致异常。有关详细信息,请参阅此链接

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

于 2013-06-07T00:38:34.340 回答