Serializing objects into XML repository
Asked Answered
P

1

0

I like XmlSerializer, because of its fire-and-forget operation. I can give XmlSerializer the object to serialize and the file to serialize to, and XmlSerializer will sort out the property names and values.

XmlWriter xmlWriter = XmlWriter.Create(projectPath + "\\" + m_projectDescriptionFileName);  // create new project description file (XML)
XmlSerializer xmlSerializer = new XmlSerializer(typeof(CustomerContactInfoViewModel));
xmlSerializer.Serialize(xmlWriter, contactInfo);
xmlWriter.Close();

I like LINQ to XML for its ability to navigate. Here's an example of a method for editing an object that's stored in XML (adapted from Greg's blog. There are also snippets for Insert and Delete.)

public void EditBilling(Billing billing)
{
    XElement node = m_billingData.Root.Elements("item").Where(i => (int)i.Element("id") == billing.ID).FirstOrDefault();

    node.SetElementValue("customer", billing.Customer);
    node.SetElementValue("type", billing.Type);
    node.SetElementValue("date", billing.Date.ToShortDateString());
    node.SetElementValue("description", billing.Description);
    node.SetElementValue("hours", billing.Hours);

    m_billingData.Save(HttpContext.Current.Server.MapPath("~/App_Data/Billings.xml"));
}

As you can see, property names and values are written out in the code, unlike XmlSerializer.

I would like to be able able to store multiple objects of different types in the same XML file (adding them at different times, not all at once). I would like to be able to deserialize them one at a time. I would like to update them one at a time.

  • Is there a way to combine the LINQ navigation with fire-and-forget convenience of XmlSerializer ?
  • Is XmlSerializer a right kind of tool for this?
  • Is there something better (short of setting up a proper database)?
  • Am I looking for something that goes by a different name?

Any suggestion, insight or reference is really appreciated!

Plainclothesman answered 22/2, 2015 at 0:2 Comment(4)
Am I missing something, or does ADO.NET fall short for you somewhere?Rudelson
@WesleyLong May be it is I that's missing something, and your comment addresses my last question "looking for something that goes by a different name?" In the meantime, I'll go look up what ADO.NET can do to XML.Plainclothesman
I just guessing here, but couldnt you create a baseObjectXmlElement which stores Xml as string/data and a typedescriptorstring? so you can store anything in the data seection and deserialize it using the typestringAyurveda
@WesleyLong Can ADO.NET infer the table and field structure of my data object? For instance, XmlSerializer can infer. If I add or remove fields from my data class, I want the serialization scheme to adapt (infer) without my intervention.Plainclothesman
C
0

Using XmlSerializer will not directly allow you to serialize multiple objects of different types into the same file. You need to tweak the reading of the xml file a bit before using XmlSerializer.

You have two options.

Option #1:

The first one being that you have a wrapper class as suggested in comments, which holds your objects. You can then use XmlSerializer to Serialize/Deserialize that specific type. You cannot directly pick a part of the xml and serialize that. This will allow you to directly serialize and deserialize the whole type/class.

Quick sample:

public class Container {
    public MyType My {get;set;}
    public OtherType Other {get;set;}
}

Container container = new Container();
...
XmlSerializer serializer = new XmlSerializer(typeof(Container));
serializer.Serialize(aWriter, container);

// deserialize

StreamReader reader = new StreamReader("container.xml");
Container c = serializer.Deserialize(reader) as Container;

Option #2:

You can read the xml file using XmlReader, and use ReadToDecendant(string) to find the current xml representation of your object (let's call it MyType) and read that xml using ReadSubTree(). Using the result from ReadSubTree() and push that to the XmlSerializer.Deserialize() method.

A quick sample would be something like:

XmlReader reader = XmlReader.Create("objects.xml");
if (reader.ReadToDecendant("MyType"))
{
    var myTypeXml = reader.ReadSubTree(); // read the whole subtree  (type)
    XmlSerializer serializer = new XmlSerializer(typeof(MyType)); // define the type
    MyType obj = serializer.Deserialize(myTypeXml); // 
}

Writing the object would be the oposite way, Serialize() the type into a (xml)string, and then replace the corresponding xml in the file.

You would really be better off using a database as data store, rather than xml. I hope you have a good reason for using files rather than a database.

Option #2 would probably be the best fit and most flexible implementation since it does not rely on wrapper classes.

Centro answered 24/2, 2015 at 18:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.