// Created by Mark Cordell
// Last modified 2008-11-22
// Lacks support for base64 and some other stuff.
////////////////////////////
using System;
//using System.IO;
//using System.Reflection;
//using System.Xml;
//using System.Xml.Serialization;
public class Util {
/// Serialize
public static string ObjToXmlStr(T obj) {
if (obj == null) return null;
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
ser.Serialize(stringWriter, obj);
stringWriter.Flush();
return stringWriter.ToString();
}
/// Deserialize
public static T XmlStrToObj(string xml) {
if (string.IsNullOrEmpty(xml)) return default(T);
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));
System.IO.StringReader stringReader = new System.IO.StringReader(xml);
System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader);
object obj = ser.Deserialize(xmlReader);
return (T)obj;
}
/// Deserialize without strict namespaces
public static T XmlStrToObjBestWeCan(string xml) {
if (string.IsNullOrEmpty(xml)) return default(T);
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(xml);
object obj = Util.XmlNodeToObj(doc.DocumentElement, typeof(T), null);
if (null == obj && (typeof(T).IsEnum || typeof(T).IsPrimitive)) {
return default(T);
} else {
return (T)obj;
}
}
#region Helper Methods
public static object XmlNodeToObj(System.Xml.XmlNode node, Type objType, System.Reflection.MemberInfo member) {
System.Xml.XmlAttribute nilAttr = node.Attributes["nil", "http://www.w3.org/2001/XMLSchema-instance"];
if (null == nilAttr) nilAttr = node.Attributes["nil"];
if (nilAttr != null && nilAttr.InnerText == "true") return null;
if (objType == typeof(string)) {
return node.InnerText;
} else if (objType.IsEnum) {
return Util.EnumParseSafe(objType, node.InnerText);
} else if (objType == typeof(DateTime)) {
return Convert.ToDateTime(node.InnerText);
} else if (objType == typeof(Decimal)) {
return Convert.ToDecimal(node.InnerText);
} else if (objType.IsPrimitive) {
if (!string.IsNullOrEmpty(node.InnerText)) {
try {
return Convert.ChangeType(node.InnerText, objType);
} catch {
return null;
}
} else {
return null;
}
} else {
Type listType = objType.GetInterface("IList");
if (listType != null) {
return Util.XmlNodeToArray(node, objType, member); // recurse
} else {
return Util.XmlNodeToClass(node, objType, member); // recurse
}
}
}
/// Not used now but may be needed in the future.
public static object XmlNodeToClass(System.Xml.XmlNode node, Type objType, System.Reflection.MemberInfo member) { // Works for structs too.
object obj = null;
if (objType.GetConstructor(Type.EmptyTypes) != null) {
obj = objType.GetConstructor(Type.EmptyTypes).Invoke(null); // Default constructor.
} else {
return null;
}
foreach (System.Reflection.FieldInfo field in objType.GetFields()) { // Public member variables.
Type memberType = field.FieldType;
System.Xml.XmlNode child = Util.GetXmlChildForMember(node, field, ref memberType);
if (child != null) {
object val = Util.XmlNodeToObj(child, memberType, field); // recurse
if (memberType.IsEnum || memberType.IsPrimitive) {
if (val != null) {
field.SetValue(obj, val);
Util.SetSpecifiedFlag(obj, field.Name);
}
} else {
field.SetValue(obj, val);
}
}
}
foreach (System.Reflection.PropertyInfo prop in objType.GetProperties()) { // Public properties.
Type memberType = prop.PropertyType;
System.Xml.XmlNode child = Util.GetXmlChildForMember(node, prop, ref memberType);
if (child != null) {
object val = Util.XmlNodeToObj(child, memberType, prop); // recurse
if (memberType.IsEnum || memberType.IsPrimitive) {
if (val != null) {
prop.SetValue(obj, val, null);
Util.SetSpecifiedFlag(obj, prop.Name);
}
} else {
prop.SetValue(obj, val, null);
}
}
}
return obj;
}
public static object XmlNodeToArray(System.Xml.XmlNode node, Type objType, System.Reflection.MemberInfo member) {
object obj = null;
if (objType.GetConstructor(Type.EmptyTypes) != null) {
obj = objType.GetConstructor(Type.EmptyTypes).Invoke(null); // Default constructor.
}
Type listElemType = objType.GetElementType();
if (null == listElemType) listElemType = typeof(object);
System.Collections.IList listObj = obj as System.Collections.IList;
if (null == listObj) {
listObj = new System.Collections.ArrayList();
}
System.Xml.Serialization.XmlElementAttribute elemAttr = null;
if (member != null) {
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlElementAttribute), false)) {
elemAttr = (System.Xml.Serialization.XmlElementAttribute)attribute;
if (string.IsNullOrEmpty(elemAttr.ElementName)) {
elemAttr.ElementName = member.Name;
}
break;
}
}
foreach (System.Xml.XmlNode chnode in node.ChildNodes) {
System.Xml.XmlElement child = chnode as System.Xml.XmlElement;
if (child != null && (null == elemAttr || elemAttr.ElementName == child.LocalName &&
(string.IsNullOrEmpty(child.NamespaceURI) || string.IsNullOrEmpty(elemAttr.Namespace) || child.NamespaceURI == elemAttr.Namespace))) {
Type childType = null;
// Is there an [XmlArrayItem] with matching name and namespace?
if (member != null) {
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlArrayItemAttribute), false)) {
System.Xml.Serialization.XmlArrayItemAttribute itemAttr = (System.Xml.Serialization.XmlArrayItemAttribute)attribute;
if (itemAttr.ElementName == child.LocalName && (string.IsNullOrEmpty(itemAttr.Namespace) || string.IsNullOrEmpty(child.NamespaceURI) || itemAttr.Namespace == child.NamespaceURI)) {
childType = itemAttr.Type;
break;
}
}
// Is there an [XmlArrayItem] with matching name ignoring namespace?
if (null == childType) {
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlArrayItemAttribute), false)) {
System.Xml.Serialization.XmlArrayItemAttribute itemAttr = (System.Xml.Serialization.XmlArrayItemAttribute)attribute;
if (itemAttr.ElementName == child.LocalName) {
childType = itemAttr.Type;
break;
}
}
}
}
if (null == childType) {
string xsiType = child.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance");
if (string.IsNullOrEmpty(xsiType)) {
xsiType = child.GetAttribute("type");
}
if (!string.IsNullOrEmpty(xsiType)) {
childType = Util.GetTypeFromXsdTypeName(xsiType);
}
}
if (null == childType) {
childType = Util.GetTypeFromXsdTypeName(child.LocalName);
}
if (null == childType) {
childType = listElemType;
}
object listItem = Util.XmlNodeToObj(child, childType, null);
listObj.Add(listItem);
}
}
if (objType.IsArray && listObj is System.Collections.ArrayList) {
Array arr = Array.CreateInstance(listElemType, listObj.Count);
for (int i = 0; i < listObj.Count; i++) {
if (!listElemType.IsValueType || listObj[i] != null) {
if (null == listObj[i] || listElemType.IsAssignableFrom(listObj[i].GetType())) {
arr.SetValue(listObj[i], i);
}
}
}
listObj = arr;
}
return listObj;
}
public static System.Xml.XmlNode GetXmlChildForMember(System.Xml.XmlNode node, System.Reflection.MemberInfo member, ref Type memberType) {
string xmlName;
string xmlNamespace;
System.Xml.XmlNode child = null;
if (memberType.GetInterface("IList") != null) {
// Is there an [XmlElement]?
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlElementAttribute), false)) {
memberType = ((System.Xml.Serialization.XmlElementAttribute)attribute).Type ?? memberType;
return node; // treat parent as child in this case.
}
}
// Is there an [XmlAttribute]?
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlAttributeAttribute), false)) {
xmlName = ((System.Xml.Serialization.XmlAttributeAttribute)attribute).AttributeName;
xmlNamespace = ((System.Xml.Serialization.XmlAttributeAttribute)attribute).Namespace;
child = Util.GetFirstAttributeByName(node, xmlName, xmlNamespace);
if (child != null) {
memberType = ((System.Xml.Serialization.XmlAttributeAttribute)attribute).Type ?? memberType;
return child;
}
}
// Is there an [XmlElement]?
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlElementAttribute), false)) {
xmlName = ((System.Xml.Serialization.XmlElementAttribute)attribute).ElementName;
xmlNamespace = ((System.Xml.Serialization.XmlElementAttribute)attribute).Namespace;
child = Util.GetFirstChildElemByTagName(node, xmlName, xmlNamespace);
if (child != null) {
memberType = ((System.Xml.Serialization.XmlElementAttribute)attribute).Type ?? memberType;
return child;
}
}
// Is there an [XmlArray]?
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlArrayAttribute), false)) {
xmlName = ((System.Xml.Serialization.XmlArrayAttribute)attribute).ElementName;
xmlNamespace = ((System.Xml.Serialization.XmlArrayAttribute)attribute).Namespace;
child = Util.GetFirstChildElemByTagName(node, xmlName, xmlNamespace);
if (child != null) return child;
}
// Try [XmlAttribute] again ignoring namespace.
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlAttributeAttribute), false)) {
xmlName = ((System.Xml.Serialization.XmlAttributeAttribute)attribute).AttributeName;
child = Util.GetFirstAttributeByName(node, xmlName, null);
if (null == child) child = Util.GetFirstChildElemByTagName(node, xmlName, null);
if (child != null) {
memberType = ((System.Xml.Serialization.XmlAttributeAttribute)attribute).Type ?? memberType;
return child;
}
}
// Try [XmlElement] again ignoring namespace.
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlElementAttribute), false)) {
xmlName = ((System.Xml.Serialization.XmlElementAttribute)attribute).ElementName;
child = Util.GetFirstChildElemByTagName(node, xmlName, null);
if (null == child) child = Util.GetFirstAttributeByName(node, xmlName, null);
if (child != null) {
memberType = ((System.Xml.Serialization.XmlElementAttribute)attribute).Type ?? memberType;
return child;
}
}
// Try [XmlArray] again ignoring namespace?
foreach (object attribute in member.GetCustomAttributes(typeof(System.Xml.Serialization.XmlArrayAttribute), false)) {
xmlName = ((System.Xml.Serialization.XmlArrayAttribute)attribute).ElementName;
child = Util.GetFirstChildElemByTagName(node, xmlName, null);
if (child != null) return child;
}
// Try by member name ignoring namespace.
child = Util.GetFirstChildElemByTagName(node, member.Name, null);
if (child != null) return child;
child = Util.GetFirstAttributeByName(node, member.Name, null);
return child;
}
public static System.Xml.XmlNode GetFirstChildElemByTagName(System.Xml.XmlNode parent, string name, string namespaceUri) {
if (parent.ChildNodes != null) {
foreach (System.Xml.XmlNode child in parent.ChildNodes) {
if (child.LocalName == name) {
if (string.IsNullOrEmpty(namespaceUri)) {
return child;
} else if (child.NamespaceURI == namespaceUri) {
return child;
}
}
}
}
return null;
}
public static System.Xml.XmlAttribute GetFirstAttributeByName(System.Xml.XmlNode parent, string name, string namespaceUri) {
if (parent.Attributes != null) {
foreach (System.Xml.XmlAttribute attr in parent.Attributes) {
if (attr.LocalName == name) {
if (string.IsNullOrEmpty(namespaceUri)) {
return attr;
} else if (attr.NamespaceURI == namespaceUri) {
return attr;
}
}
}
}
return null;
}
public static void SetSpecifiedFlag(object obj, string fieldName) {
System.Reflection.FieldInfo field = obj.GetType().GetField(fieldName + "Specified");
if (field != null && field.FieldType == typeof(bool)) {
field.SetValue(obj, true);
return;
}
System.Reflection.PropertyInfo prop = obj.GetType().GetProperty(fieldName + "Specified");
if (prop != null && prop.PropertyType == typeof(bool)) {
prop.SetValue(obj, true, null);
}
}
public static Type GetTypeFromXsdTypeName(string xsdTypeName) {
// http://msdn.microsoft.com/en-us/library/aa719879(VS.71).aspx
// http://msdn.microsoft.com/en-us/library/ms256220.aspx
if (string.IsNullOrEmpty(xsdTypeName)) return null;
int colon = xsdTypeName.IndexOf(':');
if (colon >= 0) xsdTypeName = xsdTypeName.Substring(colon + 1);
xsdTypeName = xsdTypeName.Trim();
switch (xsdTypeName) {
case "Boolean": return typeof(System.Boolean);
case "Byte": return typeof(System.SByte);
case "Date": return typeof(System.DateTime);
case "dateTime": return typeof(System.DateTime);
case "decimal": return typeof(System.Decimal);
case "Double": return typeof(System.Double);
case "duration": return typeof(System.TimeSpan);
case "Float": return typeof(System.Single);
case "gDay": return typeof(System.DateTime);
case "gMonthDay": return typeof(System.DateTime);
case "gYear": return typeof(System.DateTime);
case "gYearMonth": return typeof(System.DateTime);
case "int": return typeof(System.Int32);
case "integer": return typeof(System.Decimal);
case "long": return typeof(System.Int64);
case "short": return typeof(System.Int16);
case "string": return typeof(System.String);
case "time": return typeof(System.DateTime);
case "unsignedByte": return typeof(System.Byte);
case "unsignedInt": return typeof(System.UInt32);
case "unsignedLong": return typeof(System.UInt64);
case "unsignedShort": return typeof(System.UInt16);
}
Type t = Type.GetType(xsdTypeName, false, false);
if (null == t) t = Type.GetType(xsdTypeName, false, true);
if (null == t) {
foreach (System.Reflection.Module mod in System.Reflection.Assembly.GetExecutingAssembly().GetModules(false)) {
Type[] modtypes = mod.FindTypes(System.Reflection.Module.FilterTypeName, xsdTypeName);
if (modtypes != null && modtypes.Length > 0) return modtypes[0];
}
foreach (System.Reflection.Module mod in System.Reflection.Assembly.GetExecutingAssembly().GetModules(false)) {
Type[] modtypes = mod.FindTypes(System.Reflection.Module.FilterTypeNameIgnoreCase, xsdTypeName);
if (modtypes != null && modtypes.Length > 0) return modtypes[0];
}
}
return t;
}
public static object EnumParseSafe(Type t, string s) {
try {
return Enum.Parse(t, s, false);
} catch {
try {
return Enum.Parse(t, s, true);
} catch {
return null;
}
}
}
#endregion
}