tags:

views:

100

answers:

3

Sometimes I want to emulate stored data of my classes without setting up a round trip to the database. For example, let's say I have the following classes:

public class ShoppingCart
{
    public List<CartItem> Items {get; set;}
    public int UserID { get; set; }
}

public class CartItem
{
    public int SkuID { get; set; }
    public int Quantity  { get; set; }
    public double ExtendedCost  { get; set; }
}

Let's say I build a ShoppingCart object in memory and want to "save" it as an XML document. Is this possible via some kind of XDocument.CreateFromPOCO(shoppingCart) method? How about in the other direction: is there a built-in way to create a ShoppingCart object from an XML document like new ShoppingCart(xDoc)?

+5  A: 

XmlSerializer is one way to do it. DataContractSerializer is another. Example with XmlSerializer:

using System.XML;
using System.XML.Serialization;

//...

ShoppingCart shoppingCart = FetchShoppingCartFromSomewhere();
var serializer = new XmlSerializer(shoppingCart.GetType());
using (var writer = XmlWriter.Create("shoppingcart.xml"))
{
    serializer.Serialize(writer, shoppingCart);
}

and to deserialize it back:

var serializer = new XmlSerializer(typeof(ShoppingCart));
using (var reader = XmlReader.Create("shoppingcart.xml"))
{
    var shoppingCart = (ShoppingCart)serializer.Deserialize(reader);
}

Also for better encapsulation I would recommend you using properties instead of fields in your CartItem class.

Darin Dimitrov
Thanks for the suggestion. I had meant to use properties instead of fields. Fixed.
Ben McCormack
It took me a while to get around to testing this, but it worked perfectly. Thanks!
Ben McCormack
@Darin I wish I could give you an upvote for each time I've navigated to this answer in the past few weeks. It keeps paying dividends!
Ben McCormack
+2  A: 

You could serialize/deserialize with either the XmlSerializer or the DataContractSerializer.

Annotate your classes with DataContract and DataMember attributes and write something like this to serialize to xml to a file.

ShoppingCart cart = ...
using(FileStream writer = new FileStream(fileName, FileMode.Create))
{
   DataContractSerializer ser = new DataContractSerializer(typeof(ShoppingCart));
   ser.WriteObject(writer, cart);
}
Mikael Svenson
What if an exception is thrown during the serialization?
Darin Dimitrov
@Darin: Which you will often encounter when starting to use the DataContractSerializer. But it usually boils down to attribute annotation of your classes. The XmlSerializer is easier to use as it takes almost whatever you throw at it, but the DataContractSerializer is faster, but requires more "work" to get it up and running.
Mikael Svenson
@Mikael, I think you didn't get my point. What I meant was that if an exception is thrown you will leak a file handle which is very bad as it will lock the file and no other process be able to do anything with it until you kill the application.
Darin Dimitrov
@Darin: edited in that just now, and I need to improve at writing production code quality in code samples, not just solve the issue.
Mikael Svenson
@Mikael, StackOverflow is a quite well referenced site meaning that what you write here could potentially be seen and irresponsibly used by many people in production code and I think that basic things like disposing disposable resources is a minimum to avoid promoting bad practices. I am sure that there are many people that simply do a copy-paste from blog posts without even realizing the catastrophic implications this might have on their production systems.
Darin Dimitrov
@Darin: Very true indeed. I actually copy/pasted my code from MSDN and modified it, so they have work to do as well in their samples. Except the sample is a console app, so any file lock will be dealt with upon the program "crashing".
Mikael Svenson
A: 

Just mark up what you want to serialize with [XmlElement(name)] (or XmlAttribute, XmlRoot, etc) and then use the XmlSerializer. If you need really custom formating, implement IXmlSerializable.

AllenG