使用内存流初始化 SqlXml 并返回

5
我正在尝试从一个方法中返回SqlXml对象,该方法使用方法本地内存流进行初始化。即:
using (Stream memoryStream = new MemoryStream())
        {
            using (XmlWriter writer = XmlWriter.Create(memoryStream, new XmlWriterSettings { OmitXmlDeclaration = true }))
            {
                serializer.Serialize(writer, myList.ToArray(), ns);
                return new SqlXml(memoryStream);
            }
        }

现在调用它并尝试访问其字段的方法会失败,并出现一个“对象已释放异常”。

我快速浏览了SqlXml.cs,发现它只是保持对描述行为的流的引用。

public SqlXml(Stream value) {
            // whoever pass in the stream is responsible for closing it
            // similar to SqlBytes implementation
            if (value == null) {
                SetNull();
            }
            else  {
                firstCreateReader = true;
                m_fNotNull = true;
                m_stream = value;
            }

我希望避免调用者必须传递流并负责其生命周期。是否有其他完全初始化SqlXml对象并安全释放内存流的方法?
编辑:
一种可能的解决方案是使用临时SqlXml变量,然后通过创建读取器构造函数使用它来初始化返回对象:
using (Stream memoryStream = new MemoryStream())
        {
            using (XmlWriter writer = XmlWriter.Create(memoryStream, new XmlWriterSettings { OmitXmlDeclaration = true }))
            {
                serializer.Serialize(writer, myList.ToArray(), ns);
                SqlXml s = new SqlXml(memoryStream);
                return new SqlXml(s.CreateReader());
            }
        }

但是对我来说,这仍然看起来有点笨重。

如果调用者请求一个数据流(stream),他们应该负责处理它的释放。生成数据流的代码不应该负责释放它,因为它无法知道何时不再需要该数据流。也许你可以创建一个工厂或者使用一个IOC容器来控制数据流的创建和释放。 - Jason Down
是的,但流(stream)在序列化过程中被内部使用。调用者不应该真正关心方法如何在内部构建XML(在这种情况下是通过流)。 - Klark
没错。一旦你开始处理非托管资源,管理内存的世界就变得不那么直截了当了。也许你可以从这个回答中获取一些思路,它讨论了IDisposable以及谁负责处理传递的IDisposable实现:https://dev59.com/sG855IYBdhLWcg3w6IvV#7944828 - Jason Down
1个回答

0

using语句将在代码块退出时调用流的dispose方法。如果将MemoryStream从使用块中移除,则在返回之前不会进行处理。

class Program
{
    static void Main(string[] args)
    {
        var s = GetData();
        var r = s.CreateReader();
        while (r.Read())
        {
            if (r.NodeType == XmlNodeType.Element)
            {
                System.Console.WriteLine(r.Name);
            }
        }
        r.Close();
    }

    private static SqlXml GetData()
    {
        var mem = new MemoryStream();
        //TODO: Deserialize or query data.
        return new SqlXml(mem);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接