实现和使用IDisposable

时间:2016-12-16 16:46:00

标签: c# asp.net

我正在使用实现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
        }
    }
}

假设在一些使用它的类中注入了Processor并且执行了Process()

  • 如果再次调用Process(),包装器会发生什么? - 不会因为它只创建一次(在包装器构造函数中)并且现在它被处理了而不会抛出异常,因此它不会抛出异常
  • 只要有参考,它是否会被处置?
  • 包装器是否应该以这样的方式构建:new()" ing" ThirdPartyLib不是在构造函数中执行,而是在单独的方法中执行,比如说Begin() - 就像这样:
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()) {

2 个答案:

答案 0 :(得分:2)

你是对的。两次调用Process()可能会导致异常。完全不调用Process()会使对象不受干扰。

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

如果Processor引用了外部拥有的Wrapper,则它根本不应该处置该包装。

如果Processor在施工时获得Wrapper的所有权,那么它应该在处置时处置该包装。这意味着Processor也应该实现IDisposable

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

或者,正如您所建议的那样,如果可以修改Wrapper以按需创建ThirdPartyLib,那也可以。但要小心:调用wrapper.Begin(); wrapper.Begin();会使一个ThirdPartyLib不受约束且未引用。您需要更多地重新构建API以防止此问题成为问题,并且有效地说,这意味着将Wrapper转换为ThirdPartyLibFactory

答案 1 :(得分:1)

我认为Processor不应该处置IWrapper,因为它不是实例化它的人,也不知道它是否可以被处置或者它是否被处置注入其他物体。在这种情况下,Processor不应将using与包装器一起使用。

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