2016-12-16 109 views
0

我与实现IDisposable第三方对象的工作。为了使单元测试“能够”,我构建了一个包装器。我知道该对象实现IDisposable我的包装需要实现IDisposable以及。实施和使用IDisposable的

public interface IWrapper : IDisposable 
{ 
    void Complete(); 
} 

public class Wrapper : IWrapper 
{ 
    private readonly ThirdPartyLib lib; 

    public Wrapper() 
    { 
     lib = new ThirdPartyLib(); 
    } 

    public void Complete() 
    { 
     lib.Comlete(); 
    } 

    public void Dispose() 
    { 
     lib.Dispose(); 
    } 
} 

public class Processor : IProcessor 
{ 
    private readonly IWrapper wrapper; 
    public Processor(IWrapper wrapper) 
    { 
     this.wrapper = wrapper; 
    } 

    public void Process() 
    { 
     // do some work 
     using (wrapper) { 
      // do more work 
     } 
    } 
} 

假设处理器在某些类,它是用它和工艺注入()被执行

  • 什么happends为包装,如果我们呼叫处理()再一次? - ThirdPartyLib()不会抛出一个异常,因为它只被创建一次(在包装器的构造函数中),现在它已经被处置了
  • 只要有引用它就不会被抛弃吗?
  • 如果包装也许可以建立这样一种方式,新的()可以在构造函数,但在一个单独的方法不执行ThirdPartyLib的“ing”的,说开始() - 像这样:
public class Wrapper : IWrapper 
    { 
     private ThirdPartyLib lib; 

     public void Begin() 
     { 
      lib = new ThirdPartyLib(); 
     } 

     public void Complete() 
     { 
      lib.Comlete(); 
     } 

     public void Dispose() 
     { 
      lib.Dispose(); 
     } 
    } 

然后使用它:

using (wrapper.Begin()) { 
+1

我觉得我们没有这个大图。为什么'Processor'只处理一个被注入到构造函数中的'Wrapper'?通常我会希望你'Processor'有一个方法调用,比如'Process(IWrapper wrapper)',允许你处理这个包装器,但是我会再次进入阵营,这将是调用者必须致电'处置'在'IWrapper'上,因为它实际上拥有它。如果情况并非如此,那么我可能会在'IProcessor'上实现'IDisposable',并且在处理时只处理'IWrapper'。 –

+0

仅在IP处理器上实现IDisposable时,处理IP处理器时(在当前设计中),而不是在使用语句的“}”命中时处理包装器?这是因为(父)IP处理器持有对IWrapper的引用 - 即使我们告诉它将被放置在“}” – BobSwanson

+0

这就是为什么用DI初始化的对象应该假设它们拥有注入的object_。大多数时候,他们是由其他对象使用的单身人士,或者至少是别的东西正在控制生命。依赖于DI的对象只应该使用该对象,并假定该对象创建的任何内容都将负责在稍后对其进行核对。 DI就像_“嘿,我只想要一个对象,别人可以为我创建和删除它”_ – MickyD

回答

2

你说的没错予以关注。拨打Process()两次可能会导致异常。根本不打电话Process()会使对象不存在。

有你应该做的,而不是没有简单的规则。有多种选择,可以使用哪些选项取决于代码中不在您的问题中的其他部分。

如果Processor引用了外部拥有的Wrapper,那么它应该不会处理该包装。

如果Processor在施工时取得Wrapper的所有权,则应该在处置时处理该包装。这意味着Processor应该实现IDisposable为好。

如果可以修改Processor以根据需要创建新的Wrapper,则可以在完成Process()时处理该包装。

或者,如您所暗示的,如果Wrapper可以根据需要修改为创建ThirdPartyLib,那也可以。但要小心:拨打wrapper.Begin(); wrapper.Begin();会留下一个ThirdPartyLib未处理和未处理。您需要更多地重构您的API以防止此问题发生,并且实际上,这意味着将您的Wrapper变成ThirdPartyLibFactory

+0

你能解释一下如何调用:wrapper.Begin(); wrapper.Begin();会留下一个不存在? – BobSwanson

+0

@BobSwanson'wrapper.Begin()'创建第三方库,我们将其称为A.然后再次调用它,现在创建了第二个第三方库,我们称它为B.现在,您的私有变量'lib'指向B,没有任何东西指向A了。当你调用'wrapper.End()'时,它会调用放置B的lib.Dispose(),但A仍然存在,因为你失去了对它的唯一引用,所以不能再进行处理。 – Quantic

1

我觉得Processor不应处置IWrapper,因为它不是实例化它的人,它不知道是否可以设置,如果它被注入到其他对象。在这种情况下,Processor不应与包装使用using

处置IWrapper的代码应该放在首先实例化它的类中,因为那是知道它的生命周期的代码。