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