有没有办法在序列化一个简单的List时指定标签名称?一般来说,根据具体情况,可能可以使它工作。请参阅MSDN的
如何:指定XML流的替代元素名称。那里的示例涉及覆盖特定字段的序列化,但是也可能使用相同的技术来覆盖整个类型名称。但对我来说,这似乎太麻烦了。相反,为什么不显式处理序列化呢?
private static string SerializeByLinqAndToString<T>(
List<T> data, string rootName, string elementName)
{
XDocument document = new XDocument(
new XElement(rootName, data.Select(s => new XElement(elementName, s))));
return SaveXmlToString(document);
}
private static string SaveXmlToString(XDocument document)
{
StringBuilder sb = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(sb,
new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
{
document.Save(xmlWriter);
}
return sb.ToString();
}
打电话像这样:
SomeConfiguration config = ...; // initialize as desired
string result = SerializeByLinq(config.Bugs, "bug", "bugs");
以上仅适用于字符串列表或元素内容可以简单地是调用类型实例上的
ToString()
结果的类型列表。
在处理复杂类型时,使用.NET中完整的序列化功能可能是值得的,但如果您只有一个简单的字符串列表,则LINQ-to-XML功能非常方便。
如果您有更复杂的类型,可以将每个列表元素转换为DOM中的
XElement
并进行序列化:
private static string SerializeByLinq<T>(
List<T> data, string rootName, string elementName = null)
{
XDocument document = new XDocument(
new XElement(rootName, data.Select(t =>
ElementFromText(SerializeObject(t), elementName)
)));
return SaveXmlToString(document);
}
private static XElement ElementFromText(string xml, string name = null)
{
StringReader reader = new StringReader(xml);
XElement result = XElement.Load(reader);
if (!string.IsNullOrEmpty(name))
{
result.Name = name;
}
return result;
}
private static string SerializeObject<T>(T o)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter textWriter = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(textWriter,
new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
{
xmlSerializer.Serialize(writer, o,
new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty}));
}
return textWriter.ToString();
}
在这个第二个例子中,您可以省略子元素的元素名称,它将使用类型已经设置好的内容(例如类型名称或任何
[XmlRoot]
设置的内容)。
string
值列表,而不是其他对象。其他情况必然会更加复杂。在那些情况下,正如我所提到的,你可能会发现需要使用我提到的序列化重写技术。 - Peter DunihoXElement
内容,因此如果它看起来像XML,则必须转义/更改为实体以确保其被保留。您必须扩展基本的LINQ-to-XML技术,以进一步将T
对象序列化为包含在内容中的XElement
对象。上述仅适用于T.ToString()
生成所需值(例如原始类型如string
、int
等和类似工作的用户定义类型)。 - Peter Dunihostring.Replace()
来处理XML时,通常就会走向错误的方向。更好的方法是生成XML(例如使用你提到的Serialize<T>()
方法),然后使用XDocument
加载它,最后将该DOM复制到你正在生成的DOM中。如果我有时间,我会研究在上面的答案中添加类似于那样的东西。 - Peter Duniho