C# 在父元素中将对象序列化为XML
我有一个WPF C#程序,有一次我需要将对象序列化为XML。在其他地方,我一直在使用:C# 在父元素中将对象序列化为XML,c#,xml,wpf,serialization,C#,Xml,Wpf,Serialization,我有一个WPF C#程序,有一次我需要将对象序列化为XML。在其他地方,我一直在使用: TextWriter writer = new StreamWriter(xmlFilePath); XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE)); try { xmlSerializer.Serialize(writer, MYOBJECT); } catch (Exception ex) {
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?这样,当我以后想要反序列化对象时,我可以找到我想要的元素,并反序列化该元素中的所有内容
根据要求,这里是CreateDefaultXml()代码>:
您正试图使用XmlSerializer
直接序列化到XDocument
中的某个嵌套XElement
。不幸的是,当与一起使用XmlSerializer
直接序列化到LINQ to XMLXElement
时,实际上需要序列化到空的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);
}
}
后来
var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName);
var MYOBJECT2=doc.GetItem(objectName);
示例。您试图使用XmlSerializer
直接序列化到XDocument
中的某个嵌套的XElement
。不幸的是,当与一起使用XmlSerializer
直接序列化到LINQ to XMLXElement
时,实际上需要序列化到空的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);
}
}
后来
var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName);
var MYOBJECT2=doc.GetItem(objectName);
示例。1)什么是形状
?在shape.CreateWriter()行中代码>它未定义。2) 您能否共享CreateDefaultXml()代码>?@dbc对不起。我已经更新了问题。我更改了消息框。Show
以显示ex.InnerException
并获取System.InvalidOperationException:WriteStartDocument不能在使用ConformanceLevel.Fragment创建的写入程序上调用。
1)什么是形状
?在shape.CreateWriter()行中代码>它未定义。2) 您能否共享CreateDefaultXml()代码>?@dbc对不起。我已经更新了问题。我更改了消息框。Show
以显示ex.InnerException
并获取System.InvalidOperationException:WriteStartDocument不能在使用ConformanceLevel.Fragment创建的写入程序上调用。
var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName);