在父元素

时间:2016-05-25 16:57:09

标签: 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)
{
    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);
}

1 个答案:

答案 0 :(得分:0)

您正尝试使用XElement直接序列化XDocument内的某个嵌套XmlSerializer。不幸的是,当使用XElementXContainer.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