转移IDisposable对象的所有权和构建器设计模式

时间:2016-07-15 07:31:22

标签: c# .net idisposable

当它是创建另一个对象(直接或通过工厂,建筑商等)的对象时,我已习惯了这种方法 - 是#34;拥有的对象"它,因此管理它的寿命。

这种想法在几乎所有情况下都能正常运作。

但有时创建对象的人根本无法管理它,例如在构建器设计模式实现中:

IFoo BuildFoo()
{
    var dep = new Dep();

    return new Foo(dep);
}

因此,此处构建器无法管理dep对象的生命周期,因为:

  1. 它没有对它的引用;
  2. 它不知道Dispose它何时安全。
  3. 天真的解决方案是制作Foo : IDisposable并让它管理传递给其构造函数的Dep

    然后又出现了另一个困境:

    using (var dep = new Dep())
    {
        using (var foo = new Foo(dep))
        {
            // (1) do something with foo
        }
    
        // (2) !!! do something with dep !!!
    }
    

    上面的代码变得不安全:在(2)点,使用dep并不安全,因为Dispose已经foo了{/ 1}}。

    并且语法上没有任何东西可以表示,它的责任是管理对象的生命周期。

    所以问题是:对此有什么一般解决方案?

3 个答案:

答案 0 :(得分:1)

非常天真的实施

void Main()
{
    using (var builder = new Builder())
    {
        var foo = builder.Create();
        // do smtg
    }
}

public class Foo
{
    public Foo(Dep instance)
    {
    }
}

public class Dep : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine($"{this.GetType().Name} disposed!");
    }
}

public class Builder : IDisposable
{
    private List<IDisposable> _disposables = new List<System.IDisposable>();

    public Foo Create()
    {
        var dep = new Dep();
        _disposables.Add(dep);

        var foo = new Foo(dep);
        return foo;
    }

    public void Dispose()
    {
        foreach(var d in _disposables)
            d.Dispose();

        Console.WriteLine($"{this.GetType().Name} disposed!");
    }
}

如果某些东西拥有IDisposable,那么它应该实现IDisposable。 而且,当然,这是非常幼稚的内容,就像样本一样。

答案 1 :(得分:1)

在这种情况下,我不担心。我想,我会在这里被打成碎片,但是&#34;建筑商&#34;,&#34;工厂&#34;等等我认为可以创建一个物品并将其交给要求它的东西。

虽然构建器/工厂必须 创建对象,并且不对其执行任何操作。

当然,如果您使用new关键字修改对象,那么您将自己与该实现结合起来(即使它是通过工厂类间接的) 。您可能需要考虑依赖注入,具体取决于创建的对象的用途,在这种情况下,DI容器会根据其配置的生活方式在正确的时间为您创建对象

答案 2 :(得分:0)

您允许Foo调用构建器来实例化Dep并在需要时使用它。这种方式Foo可以管理Dep的生命周期,Foo的客户不必担心它。