views:

171

answers:

1

I've currently got an XML element in my database that maps to an object (Long story short the XML is complicated and dynamic enough to defy a conventional relational data structure without massive performance hits).

Around it I've wrapped a series of C# objects that encapsulate the structure of the XML. They work off a base class and there's multiple different possible classes it'll deserialize to with different data structures and different implemented methods. I'm currently wrapping the functionality to serialize/deserialize these into a partial class of the LINQ-generated database objects.

My current approach to this is:

    public Options GetOptions()
    {
        if (XmlOptions == null) return null;
        XmlSerializer xs = new XmlSerializer(typeof(Options));
        return (Options)xs.Deserialize(XmlOptions.CreateReader());
    }

    public void SetOptions(Options options)
    {
        if (XmlOptions == null) Options = null;
        else
        {
            XmlSerializer xs = new XmlSerializer(typeof(Options));
            using (MemoryStream ms = new MemoryStream())
            {
                xs.Serialize(ms, options);
                XmlOptions = System.Xml.Linq.XElement.Parse(System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray()));
            }
        }
    }

(To help with reading given the changed names aren't too clear, XmlOptions is the XElement element from LINQ and Options is my class it deserializes into)

Now, it works. But that's not really enough to call it "finished" to me :P It just seems incredibly inefficient to serialize XML to a memory stream, convert it to a string, then re-parse it as XML. My question is - Is this the cleanest way to do this? Is there a more efficient/tidy mechanism for doing the serialization? Is there a better approach that'll give me the same benefits (I've only got test data in the system so far, so I can change the XML structure if required)?

PS: I've renamed the fields to be more generic - so don't really need comments about naming conventions ;)

+3  A: 

XmlSerializer.Serialize has an overload that takes an XmlWriter.

You can create an XmlWriter that writes to an existing XElement by calling the CreateWriter method.

You can therefore write the following:

static readonly XmlSerializer xs = new XmlSerializer(typeof(Options));

...

var temp = new XElement("Parent");

using (var writer = temp.CreateWriter())
    xs.Serialize(writer, options);

XmlOptions = Temp.FirstNode;
SLaks
Hey, I gave that a try but I keep getting `WriteStartDocument cannot be called on writers created with ConformanceLevel.Fragment.`. Only advice I can find online is about putting settings into `XmlWriter.Create` in the form of an `XmlWriterSettings`, but `XElement`'s `CreateWriter` call doesn't take writer settings...
Tim Schneider
Then it's not possible. Sorry.
SLaks