Есть ли способ закрыть StreamWriter без закрытия BaseStream?

Моя проблема с корнем заключается в том, что когда using вызывает Dispose на StreamWriter, он также предоставляет BaseStream (та же проблема с Close).

У меня есть обходной путь для этого, но, как вы можете видеть, это связано с копированием потока. Есть ли способ сделать это без копирования потока?

Целью этого является получение содержимого строки (изначально прочитанной из базы данных) в поток, поэтому поток может быть прочитан сторонним компонентом.
NB: я не могу изменить сторонний компонент.

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    baseCopy.Seek(0, System.IO.SeekOrigin.Begin);
    return baseCopy;
}

Используется как

public void Noddy()
{
    System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
    My3rdPartyComponent.ReadFromStream(myStream);
}

В идеале я ищу мнимый метод под названием BreakAssociationWithBaseStream, например.

public System.IO.Stream CreateStream_Alternate(string value)
{
    var baseStream = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        writer.BreakAssociationWithBaseStream();
    }
    return baseStream;
}

Ответ 1

Если вы используете .NET Framework 4.5 или новее, существует перегрузка StreamWriter, с помощью которой вы можете попросить базовый поток оставаться открытым, когда автор закрытая.

В ранних версиях .NET Framework до 4.5, StreamWriter предполагает, что он владеет потоком. Параметры:

  • Не располагайте StreamWriter; просто промойте его.
  • Создайте обертку потока, которая игнорирует вызовы Close/Dispose, но проксирует все остальное. У меня есть реализация этого в MiscUtil, если вы хотите его оттуда оттуда.

Ответ 3

Просто не назовите Dispose на StreamWriter. Причина, по которой этот класс является одноразовым, заключается не только в том, что он содержит неуправляемый ресурс, но и позволяет избавиться от потока, который сам может содержать неуправляемые ресурсы. Если жизнь основного потока обрабатывается в другом месте, не нужно распоряжаться писателем.

Ответ 4

Поток памяти имеет свойство ToArray, которое можно использовать даже при закрытии потока. В Array записывается содержимое потока в массив байтов, независимо от свойства Position. Вы можете создать новый поток на основе потока, который вы написали.

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    var returnStream = new System.IO.MemoryStream( baseCopy.ToArray());
    return returnStream;
}

Ответ 5

Вам необходимо создать потомок StreamWriter и переопределить его метод dispose, всегда передавая false параметру утилизации, он заставит автору потока НЕ ​​закрываться, StreamWriter просто вызывает dispose в методе close, так что есть не нужно переопределять его (конечно, вы можете добавить все конструкторы, если хотите, у меня есть только один):

public class NoCloseStreamWriter : StreamWriter
{
    public NoCloseStreamWriter(Stream stream, Encoding encoding)
        : base(stream, encoding)
    {
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(false);
    }
}