Избегайте утилизации базового потока

Я пытаюсь высмеять некоторые файловые операции. В "реальном" объекте у меня есть:

StreamWriter createFile( string name )
{
  return new StreamWriter( Path.Combine( _outFolder, name ), false, Encoding.UTF8 ) );
}

В макетном объекте я хотел бы иметь:

StreamWriter createFile( string name )
{
  var ms = new MemoryStream();
  _files.Add( Path.Combine( _outFolder, name ), ms );
  return new StreamWriter( ms, Encoding.UTF8 ) );
}

где _files - это словарь для хранения созданных файлов для последующей проверки.

Однако, когда потребитель закрывает StreamWriter, он также предоставляет MeamoryStream...: - (

Любые мысли о том, как преследовать это?

Ответ 1

Если вы подклассифицируете MemoryStream, это будет работать, но вы должны вызвать метод ManualDispose, чтобы закрыть базовый поток.
Я не уверен, но я думаю, что этот объект будет собираться с мусором, когда он выходит за рамки.

public sealed class ManualMemoryStream : MemoryStream
{
    protected override void Dispose(bool disposing)
    {
    }
    public void ManualDispose()
    {
        base.Dispose(true);
    }
}

Edit:
Это альтернатива, если вы хотите, чтобы MemoryStream был очищен и готов к чтению сверху.

public sealed class ManualMemoryStream : MemoryStream
{
    protected override void Dispose(bool disposing)
    {
        Flush();
        Seek(0, SeekOrigin.Begin);
    }
    public void ManualDispose()
    {
        base.Dispose(true);
    }
}

Ответ 2

Характер StreamWriter заключается в том, чтобы избавиться от базового потока, когда он сам настроен. Однако, создавая (и возвращая) подкласс StreamWriter (я собираюсь назвать его LeakyStreamWriter), вы должны быть в состоянии предотвратить это поведение по умолчанию.

public class LeakyStreamWriter : StreamWriter
{
    public override void Close()
    {
        BaseStream.Close(); //close, but do not dispose
    }

    protected override void Dispose(bool disposing)
    {
        //do nothing here
    }
}

Обратите внимание, что я исхожу из предположения, что StreamWriter не имеет других компонентов для размещения, кроме базового потока, вы можете проверить разборку StreamWriter, чтобы проверить, что на самом деле выполняется в этих двух методах.

В любом случае результат использования вышеуказанного подкласса заключается в том, что базовый поток будет закрыт, но не будет удален, когда потоковик будет закрыт.