通过构造函数链传递IDisposable的对象 [英] Passing IDisposable objects through constructor chains

查看:121
本文介绍了通过构造函数链传递IDisposable的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有,一般会从数据建立在对象的小的分层次,但对于一些特殊的子类,可以从一个简单的参数列表合成。在链从子类构造函数,我运行到一个问题,如何确保处置合成流的基类构造函数需要的。它没有逃过我使用的IDisposable 反对这种方式可能是刚脏池(PLZ指教?)因为我还没有考虑的原因,但是,这个问题不谈,它。似乎相当简单(和良好的封装)



代码:

 抽象类节点{
保护的节点(流RAW)
{
//计算/生成一些基础类属性
}
}
类FilesystemNode:节点{
公共FilesystemNode(的FileStream FS)
:基地(FS)
{
//都在这里好; FS处置不是我们的责任
}
}
类CompositeNode:节点{
公共CompositeNode(IEnumerable的some_stuff)
:基地(GenerateRaw(some_stuff))$ B $从GenerateRaw b {
//流氓流目前在野生全松!
}

静流GenerateRaw(IEnumerable的some_stuff)
{
变种内容=新的MemoryStream();
//骚扰some_stuff的元素融入适当的格式,写入流
content.Seek(0,SeekOrigin.Begin);
回报率的内容;
}
}



我认识到,没有设置一<$ C $的C>的MemoryStream 不完全是坏的CLR公民的世界停止的情况下,但它仍然让我神经过敏(更不用提,我可能并不总是使用 MemoryStream的其他亚型)。这不是在范围,所以我不能明确地的Dispose()后来在构造函数中,添加一个使用语句GenerateRaw()是弄巧成拙,因为我需要从流返回。



有没有更好的办法做到这一点



先发制人的打击:




  • 是,这些属性在计算节点的构造应该是基类的一部分,不应该由(或访问)来计算的子​​类

  • 我赢了 ŧ要求流被传递到CompositeNode(它的格式应该是无关的调用者)

  • 前一次迭代曾在基类中值计算为一个单独的保护方法,然后我只是叫在各亚型构造年底,移动 GenerateRaw()的身体成的身体using语句 CompositeNode 构造函数。但要求要求每个构造,不能够的重复,以保证它的每个子类中运行过(A 节点不是节点,语义,没有这些属性初始化)给我神经过敏远远高于(潜在的)资源在这里呢。


解决方案
CompositeNode >创建的流 - CompositeNode 有责任除非一些其他的代码明确指出它会采取上。这里的一个选择是,基本构造函数允许这个通过保护过载,但排列顺序意味着这将是很难准确地知道何时可以安全处置它。 A 虚拟方法将允许你这样做,但你不应该真的叫虚拟方法构造。



不知重构,以便有一个的初始化的(加载)方法(你单独建设)的调用会更好。也许受保护的虚拟方法,并通过公共静态方法将其暴露。


I've got a small hierarchy of objects that in general gets constructed from data in a Stream, but for some particular subclasses, can be synthesized from a simpler argument list. In chaining the constructors from the subclasses, I'm running into an issue with ensuring the disposal of the synthesized stream that the base class constructor needs. Its not escaped me that the use of IDisposable objects this way is possibly just dirty pool (plz advise?) for reasons I've not considered, but, this issue aside, it seems fairly straightforward (and good encapsulation).

Codes:

abstract class Node {
    protected Node (Stream raw)
    {
        // calculate/generate some base class properties
    }
}
class FilesystemNode : Node {
    public FilesystemNode (FileStream fs)
        : base (fs)
    {
        // all good here; disposing of fs not our responsibility
    }
}
class CompositeNode : Node {
    public CompositeNode (IEnumerable some_stuff)
        : base (GenerateRaw (some_stuff))
    {
        // rogue stream from GenerateRaw now loose in the wild!
    }

    static Stream GenerateRaw (IEnumerable some_stuff)
    {
        var content = new MemoryStream ();
        // molest elements of some_stuff into proper format, write to stream
        content.Seek (0, SeekOrigin.Begin);
        return content;
    }
}

I realize that not disposing of a MemoryStream is not exactly a world-stopping case of bad CLR citizenship, but it still gives me the heebie-jeebies (not to mention that I may not always be using a MemoryStream for other subtypes). It's not in scope, so I can't explicitly Dispose () it later in the constructor, and adding a using statement in GenerateRaw () is self-defeating since I need the stream returned.

Is there a better way to do this?

Preemptive strikes:

  • yes, the properties calculated in the Node constructor should be part of the base class, and should not be calculated by (or accessible in) the subclasses
  • I won't require that a stream be passed into CompositeNode (its format should be irrelevant to the caller)
  • The previous iteration had the value calculation in the base class as a separate protected method, which I then just called at the end of each subtype constructor, moved the body of GenerateRaw () into a using statement in the body of the CompositeNode constructor. But the repetition of requiring that call for each constructor and not being able to guarantee that it be run for every subtype ever (a Node is not a Node, semantically, without these properties initialized) gave me heebie-jeebies far worse than the (potential) resource leak here does.

解决方案

CompositeNode created the stream - CompositeNode has the responsibility unless some other code explicitly states it'll take that on. One option here would be for the base-constructor to allow this via a protected overload, but the ordering means that it would be hard to know exactly when it is safe to dispose it. A virtual method would allow you to do this, but you shouldn't really call virtual methods in constructors.

I wonder if refactoring so that there is an initialize (Load) method (that you call separately to construction) would be better. Perhaps a protected virtual method, and expose it via a public static method.

这篇关于通过构造函数链传递IDisposable的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆