If you need to serialize your business objects into XML you may also need to generate automatically XML Schema so you can check the XML against that schema before try to deserialize it. This is one utility that will do that for you. Now, let’s first see one utility that will do basic XML serialization and deserialization objects.
public static class SerializationUtil
{
private static readonly Dictionary<Type, XmlSerializer> _serializersCache =
new Dictionary<Type, XmlSerializer>();
private static XmlSerializer GetSerializer(Type type)
{
XmlSerializer xs;
if (!_serializersCache.TryGetValue(type, out xs))
{
xs = new XmlSerializer(type);
_serializersCache[type] = xs;
}
return xs;
}
public static string ToXml<T>(T obj)
{
var xs = GetSerializer(typeof(T));
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
xs.Serialize(writer, obj);
writer.Close();
}
return sb.ToString();
}
public static T FromXml<T>(string xml)
{
T a;
var xs = GetSerializer(typeof(T));
using (var reader = new StringReader(xml))
{
a = (T)xs.Deserialize(reader);
reader.Close();
}
return a;
}
}
You can use it as:
// serialize business object into xml string
var xmlString = SerializationUtil.ToXml<MyObj>(obj);
// deserialize xml string into business object
var obj = SerializationUtil.FromXml<MyObj>(xmlString);
Now, to generate XML schema from the interface your object implements you can use this utility:
public static class InterfaceToXsdUtil
{
private const string XMLSchema = "http://www.w3.org/2001/XMLSchema";
private const string XS = "xs";
private static bool IsFloat(Type type)
{
return (type == typeof (Int64) ||
type == typeof (UInt64) ||
type == typeof (Single) ||
type == typeof (Double) ||
type == typeof (Decimal));
}
private static bool IsInt(Type type)
{
return (type == typeof(Byte) ||
type == typeof(SByte) ||
type == typeof(Int16) ||
type == typeof(UInt16) ||
type == typeof(Int32) ||
type == typeof(UInt32));
}
private static void WriteType(XmlWriter xtw, string name,
Type type, int depth,
Func<XmlWriter, string, Type, bool> customProc)
{
if (customProc != null && customProc(xtw, name, type))
{
return;
}
xtw.WriteStartElement(XS, "element", XMLSchema);
{ // attributes
xtw.WriteAttributeString("name", name);
if (depth > 0)
{
xtw.WriteAttributeString("minOccurs", "0");
xtw.WriteAttributeString("maxOccurs", "1");
}
xtw.WriteStartElement(XS, "complexType", XMLSchema);
{
xtw.WriteStartElement(XS, "sequence", XMLSchema);
{
foreach (var pi in type.GetProperties())
{
var propType = pi.PropertyType;
if (propType.IsClass && propType != typeof(string))
{
WriteType(xtw, pi.Name, pi.PropertyType, depth + 1, customProc);
}
else
{
xtw.WriteStartElement(XS, "element", XMLSchema);
{ // attributes
xtw.WriteAttributeString("name", pi.Name);
if (propType.IsValueType)
{
xtw.WriteAttributeString("minOccurs", "1");
}
else
{
xtw.WriteAttributeString("minOccurs", "0");
}
if (IsFloat(propType))
{
xtw.WriteAttributeString("type", "xs:decimal");
}
else if (IsInt(propType))
{
xtw.WriteAttributeString("type", "xs:integer");
}
else if (propType == typeof(bool))
{
xtw.WriteAttributeString("type", "xs:boolean");
}
else if (propType == typeof(DateTime))
{
xtw.WriteAttributeString("type", "xs:date");
}
else // if(propType == typeof(string))
{
xtw.WriteAttributeString("type", "xs:string");
}
}
xtw.WriteEndElement();
}
}
}
xtw.WriteEndElement();
}
xtw.WriteEndElement();
}
xtw.WriteEndElement();
}
public static string ToXsd<T>()
{
var type = typeof(T);
var root = type.Name.StartsWith("I") ? type.Name.Substring(1) : type.Name;
return ToXsd<T>(root, null);
}
public static string ToXsd<T>(string root)
{
return ToXsd<T>(root, null);
}
public static string ToXsd<T>(string root,
Func<XmlWriter, string, Type, bool> customProc)
{
var type = typeof (T);
var sb = new StringBuilder();
using (var xtw = new XmlTextWriter(new StringWriter(sb)))
{
xtw.Formatting = Formatting.Indented;
xtw.WriteStartElement(XS, "schema", XMLSchema);
{ // attributes
xtw.WriteAttributeString("id", root);
xtw.WriteAttributeString("xmlns", "");
xtw.WriteAttributeString("xmlns:msdata",
"urn:schemas-microsoft-com:xml-msdata");
}
WriteType(xtw, root, type, 0, customProc);
xtw.WriteEndElement();
}
return sb.ToString();
}
}
The way you use it is as follow:
var xsdString = InterfaceToXsdUtil.ToXsd<IMyBusinessObject>();