using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using log4net; using System.Xml; using System.Reflection; namespace SERemoteLib { /// /// The serializer to generate an XML document. This class offers some functions to create general xml-elements /// for the transfer of data over SOAP to a PDK instrument. /// public sealed class PdkXmlSerializer { private static IDictionary typeMappings; /// /// The XmlElement name of a parameterlist-element. /// public static readonly String ParamlistElementname = "param-list"; /// /// The XmlElement name of a parameter-element. /// public static readonly String ParamElementname = "param"; /// /// The XmlElement name of a parameter-element. /// public static readonly String ItemElementname = "item"; /// /// The XmlAttribute name of a type-attribute. /// public static readonly String TypeAttributename = "type"; /// /// The XmlAttribute name of a sequence type-attribute. /// public static readonly String SequenceTypeAttributename = "sequenceType"; /// /// The XmlAttribute name of a name-attribute. /// public static readonly String NameAttributename = "name"; /// /// The XmlElement name of a method-element. /// public static readonly String MethodElementname = "method"; /// /// The XmlElement name of a methodfunction-element. /// public static readonly String MethodfunctionElementname = "mf"; /// /// The XmlElement name of a record-element. /// public static readonly String RecordElementname = "record"; private static readonly ILog logger = LogManager.GetLogger(typeof(PdkXmlSerializer)); /// /// Initializes a new instance of the class. /// private PdkXmlSerializer() { } /// /// Serializes the record into the PDK specific XML. /// /// The browsable screen record. /// public static string SerializeRecord(object record) { XmlDocument doc = new XmlDocument(); XmlElement recordElement = CreateRecordElement(record, doc); doc.AppendChild(recordElement); if (logger.IsDebugEnabled) { logger.Debug("Serialized " + record.GetType().ToString() + " into " + doc.InnerXml); } return doc.InnerXml.Replace("\r\n", " ").Replace("\n", " ").Replace("\t", " "); } private static XmlElement CreateRecordElement(object recordObject, XmlDocument doc) { XmlElement recordElement = doc.CreateElement(RecordElementname); XmlAttribute recordTypeAttribute = doc.CreateAttribute(TypeAttributename); recordTypeAttribute.InnerText = recordObject.GetType().Name; recordElement.Attributes.Append(recordTypeAttribute); XmlElement paramListElement = CreateParameterListElement(recordObject, doc); recordElement.AppendChild(paramListElement); return recordElement; } /// /// Initializes the type-mapping dictonary. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "add collection members")] static PdkXmlSerializer() { typeMappings = new Dictionary(); typeMappings.Add(typeof(string), "wstring"); typeMappings.Add(typeof(bool), "boolean"); typeMappings.Add(typeof(short), "short"); typeMappings.Add(typeof(DateTime), "datetime"); typeMappings.Add(typeof(decimal), "decfloat"); typeMappings.Add(typeof(int), "long"); typeMappings.Add(typeof(byte), "octet"); //typeMappings.Add(typeof(decfloat), "decfloat"); typeMappings.Add(typeof(double), "double"); } /// /// Maps a to the according PDK type. /// /// /// public static String MapType(Type type) { if (typeMappings.ContainsKey(type)) { return typeMappings[type]; } else if (type.IsEnum) { return "short"; } else if (type.IsArray) { return "sequence"; } else { return "record"; } } /// /// Serializes the value into the according XML representation. /// /// The value to serialize. MUST NOT be null /// XML string representing the value. public static String SerializeValue(object val) { String returnValue = null; if (val == null) { throw new ArgumentException("The argument val MUST NOT be null."); } if (typeMappings.ContainsKey(val.GetType())) { if (val.GetType() == typeof(string)) { returnValue = (string)val; } else if (val.GetType() == typeof(bool)) { returnValue = XmlConvert.ToString((bool)val); } else if (val.GetType() == typeof(short)) { returnValue = XmlConvert.ToString((short)val); } else if (val.GetType() == typeof(DateTime)) { returnValue = XmlConvert.ToString((DateTime)val, "yyyy-MM-dd HH:mm:ss"); } else if (val.GetType() == typeof(decimal)) { returnValue = XmlConvert.ToString((decimal)val); } else if (val.GetType() == typeof(int)) { returnValue = XmlConvert.ToString((int)val); } else if (val.GetType() == typeof(byte)) { returnValue = XmlConvert.ToString((byte)val); } //else if (val.GetType() == typeof(decfloat)) //{ // returnValue = ((decfloat)val).Value; //} else if (val.GetType() == typeof(double)) { returnValue = XmlConvert.ToString((double)val); } } else if (val.GetType().IsEnum) { returnValue = XmlConvert.ToString((int)val); } return returnValue; } /// /// Creates the element param-list element with all its param subelements. Each property of the /// is added as a param elemment. /// /// /// /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object")] private static XmlElement CreateParameterListElement(object paramObject, XmlDocument doc) { XmlElement paramListElement = doc.CreateElement(ParamlistElementname); //add parameters PropertyInfo[] properties = paramObject.GetType().GetProperties(); foreach (PropertyInfo property in properties) { bool ignoreThisProperty = false; foreach (System.Xml.Serialization.XmlIgnoreAttribute xmlIgnoreAttribute in property.GetCustomAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute), false)) { ignoreThisProperty = true; break; } if (!ignoreThisProperty) { XmlElement paramElement = CreateParameterElement(property, paramObject, doc); paramListElement.AppendChild(paramElement); } } return paramListElement; } /// /// Creates the param element for the . /// /// /// /// /// private static XmlElement CreateParameterElement(PropertyInfo property, object paramObject, XmlDocument doc) { XmlElement paramElement = doc.CreateElement(ParamElementname); XmlAttribute nameAttribute = doc.CreateAttribute(NameAttributename); nameAttribute.InnerText = property.Name; paramElement.Attributes.Append(nameAttribute); XmlAttribute paramTypeAttribute = doc.CreateAttribute(TypeAttributename); paramTypeAttribute.InnerText = MapType(property.GetGetMethod().ReturnType); paramElement.Attributes.Append(paramTypeAttribute); object val = property.GetValue(paramObject, null); if (val != null) { if (paramTypeAttribute.InnerText == "record") { XmlElement recordElement = CreateRecordElement(val, doc); paramElement.AppendChild(recordElement); } else if (paramTypeAttribute.InnerText == "sequence") { XmlAttribute seqTypeAttribute = doc.CreateAttribute(SequenceTypeAttributename); bool isComplexTypeSequence; if (property.PropertyType == typeof(string[])) { seqTypeAttribute.InnerText = MapType(typeof(string)); isComplexTypeSequence = false; } else { seqTypeAttribute.InnerText = RecordElementname; isComplexTypeSequence = true; } paramElement.Attributes.Append(seqTypeAttribute); Array ar = (Array)val; for (int i = 0; i < ar.Length; ++i) { XmlElement itemElement = doc.CreateElement(ItemElementname); if (isComplexTypeSequence) { XmlElement recordElement = CreateRecordElement(ar.GetValue(i), doc); itemElement.AppendChild(recordElement); } else { itemElement.InnerText = ar.GetValue(i).ToString(); } paramElement.AppendChild(itemElement); } } else { paramElement.InnerText = SerializeValue(val); } } return paramElement; } } }