我有一个WPF C#程序,有一次我需要将对象序列化为XML。在其他地方,我一直在使用它:
TextWriter writer = new StreamWriter(xmlFilePath);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE));
try
{
xmlSerializer.Serialize(writer, MYOBJECT);
}
catch (Exception ex)
{
MessageBox.Show("Exception occured while writing to Xml" + ex.Message);
}
finally
{
writer.Close();
}
这很棒,但这意味着我必须为每个要序列化的对象提供不同的XML文件。如何使用此方法(使用最少的修改)将对象序列化为XML WITHIN父元素?这样,当我想稍后反序列化该对象时,我可以找到我想要的元素,并反序列化该元素中的所有内容。
根据要求,此处为CreateDefaultXml();
:
static void CreateDefaultXml()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<StoredObjects></StoredObjects>");
XmlNode root = doc.DocumentElement;
try
{
doc.Save(xmlFilePath);
}
catch (Exception ex)
{
Console.WriteLine("Exception occured while creating Xml" + ex.InnerException);
}
}
修改
目前,这就是我所拥有的(但它会引发异常There was an error generating the XML document.
)
if (!File.Exists(xmlFilePath))
CreateDefaultXml();
XDocument doc = XDocument.Load(xmlFilePath);
var element = doc.Descendants("Object").Where(x => x.Attribute("Name").Value.Equals("objectName")).SingleOrDefault();
if (element == null)
{
element = new XElement("Object", new XAttribute("Name", objectName));
doc.Element("StoredObjects").Add(element);
}
XmlWriter writer = element.CreateWriter();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE));
try
{
xmlSerializer.Serialize(writer, MYOBJECT);
}
catch (Exception ex)
{
MessageBox.Show("Exception occured while writing to Xml: " + ex.Message);
}
finally
{
writer.Close();
doc.Save(xmlFilePath);
}
答案 0 :(得分:0)
您正尝试使用XElement
直接序列化XDocument
内的某个嵌套XmlSerializer
。不幸的是,当使用XElement
与XContainer.CreateWriter()
一起直接序列化到LINQ-to-XML XmlSerializer
时,实际上有必要将序列化为空XDocument
从而创建其根元素。 (我不确定为什么存在此限制,但确实如此。)由于这不能满足您的需求,因此很容易序列化为临时 XDocument
,删除其根目录然后,将该节点添加到整个元素层次结构中。
此外,使用已存储XML数据的objectName
向数据库添加对象时,需要删除旧数据。
我将您的代码重构为扩展方法以实现此目的:
public static class XmlExtensions
{
public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
{
using (var reader = element.CreateReader())
{
object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
if (result is T)
return (T)result;
}
return default(T);
}
public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer = null)
{
var doc = new XDocument();
using (var writer = doc.CreateWriter())
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj);
var element = doc.Root;
if (element != null)
element.Remove();
return element;
}
public static XName ContainerElementName { get { return (XName)"Object"; } }
public static XName ContainerAttributeName { get { return (XName)"Name"; } }
public static XElement SetItem<T>(this XDocument doc, string attributeValue, T obj)
{
return doc.SetItem(ContainerElementName, ContainerAttributeName, attributeValue, obj);
}
static XElement SetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue, T obj)
{
if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null)
throw new ArgumentNullException();
if (doc.Root == null)
throw new ArgumentException("doc.Root == null");
var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault();
if (container == null)
{
container = new XElement(containerElementName, new XAttribute(containerAttributeName, attributeValue));
doc.Root.Add(container);
}
else
{
// Remove old content.
container.RemoveNodes();
}
var element = obj.SerializeToXElement();
container.Add(element);
return element;
}
public static T GetItem<T>(this XDocument doc, string attributeValue)
{
return doc.GetItem<T>(ContainerElementName, ContainerAttributeName, attributeValue);
}
static T GetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue)
{
if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null)
throw new ArgumentNullException();
if (doc.Root == null)
throw new ArgumentException("doc.Root == null");
var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault();
if (container == null)
return default(T);
var element = container.Elements().SingleOrDefault();
if (element == null)
return default(T);
return element.Deserialize<T>();
}
public static XDocument CreateDefaultXDocument()
{
var xml = @"<StoredObjects></StoredObjects>";
return XDocument.Parse(xml);
}
}
现在你可以做到
doc.AddItem(MYOBJECT, objectName);
以后
var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName);
示例fiddle。