我喜欢 XmlSerialize 的工作方式,如此简单、优雅,并且具有属性 =p 但是,在序列化到 xml 文件之前构建所有对象的集合时,我遇到了内存不足问题。
我正在从 SQL 数据库填充一个对象,并打算使用 XmlSerialize 将对象写入 XML。它对于小子集非常有用,但如果我尝试从数据库中获取所有对象,则会出现内存不足异常。
XmlSerialize 是否有某种功能可以让我从数据库中批量抓取 100 个对象,然后写入它们,抓取下一批 100 个对象并附加到 xml?
我希望我不必陷入 XmlDocument 或需要更多手动编码工作的东西......
XmlSerializer
事实上,可以在序列化时将可枚举的数据传入和传出。它对实现的类有特殊处理IEnumerable<T>
。来自docs:
XmlSerializer 对实现 IEnumerable 或 ICollection 的类给予特殊处理。实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。 Add 方法的参数必须与从 GetEnumerator 返回的值的 Current 属性返回的类型相同,或者该类型的基数之一。
当序列化此类时,XmlSerializer
只需迭代将每个当前值写入输出流即可枚举。它does not首先将整个可枚举加载到列表中。因此,如果您有一些在类型结果中动态分页的 Linq 查询T
从数据库中分块(例如here),您可以使用以下包装器将它们全部序列化,而无需一次加载它们:
// Proxy class for any enumerable with the requisite `Add` methods.
public class EnumerableProxy<T> : IEnumerable<T>
{
[XmlIgnore]
public IEnumerable<T> BaseEnumerable { get; set; }
public void Add(T obj)
{
throw new NotImplementedException();
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
if (BaseEnumerable == null)
return Enumerable.Empty<T>().GetEnumerator();
return BaseEnumerable.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
请注意,此类仅适用于序列化,不适用于反序列化。以下是如何使用它的示例:
public class RootObject<T>
{
[XmlIgnore]
public IEnumerable<T> Results { get; set; }
[XmlArray("Results")]
public EnumerableProxy<T> ResultsProxy {
get
{
return new EnumerableProxy<T> { BaseEnumerable = Results };
}
set
{
throw new NotImplementedException();
}
}
}
public class TestClass
{
XmlWriter xmlWriter;
TextWriter textWriter;
public void Test()
{
try
{
var root = new RootObject<int>();
root.Results = GetResults();
using (textWriter = new StringWriter())
{
var settings = new XmlWriterSettings { Indent = true, IndentChars = " " };
using (xmlWriter = XmlWriter.Create(textWriter, settings))
{
(new XmlSerializer(root.GetType())).Serialize(xmlWriter, root);
}
var xml = textWriter.ToString();
Debug.WriteLine(xml);
}
}
finally
{
xmlWriter = null;
textWriter = null;
}
}
IEnumerable<int> GetResults()
{
foreach (var i in Enumerable.Range(0, 1000))
{
if (i > 0 && (i % 500) == 0)
{
HalfwayPoint();
}
yield return i;
}
}
private void HalfwayPoint()
{
if (xmlWriter != null)
{
xmlWriter.Flush();
var xml = textWriter.ToString();
Debug.WriteLine(xml);
}
}
}
如果你设置了中断HalfwayPoint()
,您将看到一半的 XML 已被写出,同时仍在迭代可枚举对象。 (当然,我只是为了测试目的而写入字符串,而您可能会写入文件。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)