2016-05-25 2 views
1

У меня есть программа WPF C#, и в какой-то момент мне нужно сериализовать объекты в XML. В других местах, я использую это:Сериализуйте объект в XML WITHIN для родительского элемента

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();:

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); 
    } 
} 

EDIT:

В настоящее время, это то, что у меня есть (но он бросает исключение 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

1) Что такое 'shape'? В строке 'shape.CreateWriter();' она не определена. 2) Можете ли вы поделиться 'CreateDefaultXml(); '? – dbc

+0

@dbc Извините. Я обновил вопрос – derekantrican

+1

Я изменил 'MessageBox.Show', чтобы показать' ex.InnerException' и получить 'System.InvalidOperationException: WriteStartDocument не может быть вызван для писателей, созданных с ConformanceLevel.Fragment.' – derekantrican

ответ

0

Вы пытаетесь сериализовать непосредственно на некоторые вложенные XElement внутри XDocument с использованием XmlSerializer. К сожалению, кажется, что при сериализации непосредственно с LINQ-to-XML XElement с использованием XmlSerializer вместе с XContainer.CreateWriter(), на самом деле необходимо сериализовать на пустой XDocument, тем самым создав свой корневой элемент. (Я не уверен, почему это ограничение существует, но оно есть.) Поскольку это не соответствует вашим потребностям, легко сериализовать на временныйXDocument, удалить его корневой узел, а затем добавить этот узел в свою общую иерархию элементов ,

Кроме того, при добавлении объекта в вашу базу данных с помощью objectName, который уже хранит данные XML, вам необходимо удалить старые данные.

Я реструктурировать свой код в методы расширения для достижения этой цели:

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.

Смежные вопросы