My question is the following.
I have xml that is versioned by a namespace. I want to serialize this received xml into the appropriate object, but the only way I know to do this means I have to process the xml two times. First to discover the namespace, and then in order to serialize to the object of the proper type based on the discovered namespace. This seems dreadfully inefficient to me, and there must be some way using generics or something to get the appropriate type of object back without an 'if namespace == x then serialze to that' check.
Below is a sample of the only way I know to accomplish this. Is there a better or more efficient way?
Thanks
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace TestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod3()
{
//Build up an employee object to xml
Schema.v2.Employee employee = new Schema.v2.Employee { FirstName = "First", LastName = "Last" };
string xml = employee.ObjectToXml<Schema.v2.Employee>();
//Now pretend I don't know what type I am receiving.
string nameSpace = GetNamespace(xml);
Object newemp;
if (nameSpace == "Employee.v2")
newemp = XmlSerializationExtension.XmlToObject<Schema.v2.Employee>(null, xml);
else
newemp = XmlSerializationExtension.XmlToObject<Schema.v1.Employee>(null, xml);
// Check to make sure that the type I got was what I made.
Assert.AreEqual(typeof(Schema.v2.Employee), newemp.GetType());
}
public string GetNamespace(string s)
{
XDocument z = XDocument.Parse(s);
var result = z.Root.Attributes().
Where(a => a.IsNamespaceDeclaration).
GroupBy(a => a.Name.Namespace == XNamespace.None ? String.Empty : a.Name.LocalName,
a => XNamespace.Get(a.Value)).
ToDictionary(g => g.Key,
g => g.First());
foreach (System.Xml.Linq.XNamespace item in result.Values)
if (item.NamespaceName.Contains("Employee")) return item.NamespaceName;
return String.Empty;
}
}
public static class XmlSerializationExtension
{
public static string ObjectToXml<T>(this T Object)
{
XmlSerializer s = new XmlSerializer(Object.GetType());
using (StringWriter writer = new StringWriter())
{
s.Serialize(writer, Object);
return writer.ToString();
}
}
public static T XmlToObject<T>(this T Object, string xml)
{
XmlSerializer s = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(xml))
{
object obj = s.Deserialize(reader);
return (T)obj;
}
}
}
}
namespace Schema.v1
{
[XmlRoot(ElementName = "Employee", Namespace= "Employee.v1", IsNullable = false)]
public class Employee
{
[XmlElement(ElementName = "FirstName")]
public string FirstName { get; set; }
[XmlElement(ElementName = "LastName")]
public string LastName { get; set; }
}
}
namespace Schema.v2
{
[XmlRoot(ElementName = "Employee", Namespace = "Employee.v2", IsNullable = false)]
public class Employee
{
[XmlAttribute(AttributeName = "FirstName")]
public string FirstName { get; set; }
[XmlAttribute(AttributeName = "LastName")]
public string LastName { get; set; }
}
}