/* Test.Module.Channel.DataArray.cs Copyright © 2009 Diversified Technical Systems, Inc. All Rights Reserved */ using System; using System.Collections.Generic; using System.Reflection; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; using DTS.Common.Utilities; using DTS.Common.Utilities.DotNetProgrammingConstructs; namespace DTS.Serialization { // *** see Test.cs *** public partial class Test { // *** see Test.Module.cs *** public partial class Module { // *** see Test.Module.Channel.cs *** public partial class Channel { /// /// Representation of serializable channel data. /// /// /// /// The actual type of this channel data's datum. /// /// public class DataArray : Exceptional, IXmlSerializable { private readonly string DataXmlTag = "Data"; private readonly string DataLengthXmlTag = "Length"; private readonly string DataTypeXmlTag = "Type"; private readonly string DatumXmlTag = "Datum"; private readonly string DatumValueXmlTag = "Value"; private readonly string DataAdcToMvScaleFactorTag = "ScaleFactorMv"; private readonly string DataMvPerEuTag = "SensitivityMvEu"; /// /// Method for converting a of the generic data type to /// a DataArray. /// /// /// /// The of the generic data type to be converted into a /// DataArray. /// /// /// /// A DataArray containing the specified values. /// /// public static implicit operator DataArray(List dataList) { return new DataArray(dataList.ToArray()); } /// /// Method for converting a DataArray of the generic data type to a /// of the generic data type. /// /// /// /// The DataArray of the specified generic type to be converted into a . /// /// /// /// A of the specified generic type. /// /// public static implicit operator List(DataArray dataArray) { return new List(dataArray.Values); } /// /// Initialize an instance of the Data class. /// public DataArray() { } /// /// Initialize an instance of the Data class. /// /// /// /// The values with which to initialize this data collection. /// /// public DataArray(DataType[] values) { try { Values = values; } catch (System.Exception ex) { throw new Exception("encountered problem constructing Test.Module.Channel.DataArray", ex); } } /// /// Get all of the data values in an array. /// public DataType[] Values { //get { return _Values.Value; } get { if (!_Values.IsInitialized || null == _Values.Value) { return new DataType[0]; } return _Values.Value; } set => _Values.Value = value; } private readonly Property _Values = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.Values", null, false ); /// /// Get/set the ADC->MV scale factor for this data. /// public double ScaleFactorMv { get => _ScaleFactorMv.Value; set => _ScaleFactorMv.Value = value; } private readonly Property _ScaleFactorMv = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.ScaleFactorMv", 0.0, false ); public double ScaleFactorEU { get => _ScaleFactorEU.Value; set => _ScaleFactorEU.Value = value; } private readonly Property _ScaleFactorEU = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.ScaleFactorEU", 0.0, false ); public bool UseEUScaleFactors { get => _UseEUScaleFactors.Value; set => _UseEUScaleFactors.Value = value; } private readonly Property _UseEUScaleFactors = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.UseEUScaleFactors", false, true ); public short DataZeroLevel { get => _DataZeroLevel.Value; set => _DataZeroLevel.Value = value; } private readonly Property _DataZeroLevel = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.DataZeroLevel", 0, false ); /// /// Get/set the Unit Conversion for this data. /// public double UnitConversion { get => _UnitConversion.Value; set => _UnitConversion.Value = value; } private readonly Property _UnitConversion = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.UnitConversion", 1.0, true ); /// /// Get/set the Multiplier for this data. /// public double Multiplier { get => _Multiplier.Value; set => _Multiplier.Value = value; } private readonly Property _Multiplier = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.Multiplier", 1.0, true ); /// /// Get/set the Modify Offset for this data. /// public double UserOffsetEU { get => _UserOffsetEU.Value; set => _UserOffsetEU.Value = value; } private readonly Property _UserOffsetEU = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.UserOffsetEU", 0.0, true ); /// /// Get/set the ADC->EU scale factor for this data. /// public double MvPerEu { get => _MvPerEu.Value; set => _MvPerEu.Value = value; } private readonly Property _MvPerEu = new Property( typeof(DataArray).Namespace + ".Test.Module.Channel.DataArray.MvPerEu", 0.0, false ); /// /// Write XML serialization for this object to the specified writer. /// /// /// /// The to which this object's XML serialization /// will be written. /// /// public void WriteXml(XmlWriter writer) { try { var cult = new System.Globalization.CultureInfo(""); var dataLength = Values.Length; writer.WriteStartElement(DataXmlTag); writer.WriteAttributeString(DataLengthXmlTag, dataLength.ToString(cult)); writer.WriteAttributeString(DataTypeXmlTag, typeof(DataType).FullName); writer.WriteAttributeString(DataAdcToMvScaleFactorTag, ScaleFactorMv.ToString(cult)); writer.WriteAttributeString(DataMvPerEuTag, MvPerEu.ToString(cult)); for (var i = 0; i < dataLength; i++) { writer.WriteStartElement(DatumXmlTag); writer.WriteAttributeString(DatumValueXmlTag, Values[i].ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); } catch (System.Exception ex) { throw new Exception("encountered problem converting DTS.Serialization.Test.Module.Channel.Data object to XML", ex); } } /// /// Read XML serialization for this object from the specified reader. /// /// /// /// The from which this object's XML serialization /// will be read. /// /// public void ReadXml(XmlReader reader) { try { var cult = new System.Globalization.CultureInfo(""); reader.MoveToContent(); Type dataType = null; int dataLength; try { string scaleFactorMvString = null; try { scaleFactorMvString = reader.GetAttribute(DataAdcToMvScaleFactorTag); } catch (System.Exception ex) { throw new Exception("encountered problem extracting ADC->MV scaling factor from XML", ex); } string mvPerEuString = null; try { mvPerEuString = reader.GetAttribute(DataMvPerEuTag); } catch (System.Exception ex) { throw new Exception("encountered problem extracting sensitivity MV/EU factor from XML", ex); } string dataTypeString = null; try { dataTypeString = reader.GetAttribute(DataTypeXmlTag); } catch (System.Exception ex) { throw new Exception("encountered problem extracting data type name from XML", ex); } dataType = null; try { dataType = Type.GetType(dataTypeString); } catch (System.Exception ex) { throw new Exception("encountered problem instantiating type " + (null != dataTypeString ? "\"" + dataTypeString + "\"" : "<>"), ex); } string dataLengthString = null; try { dataLengthString = reader.GetAttribute(DataLengthXmlTag); } catch (System.Exception ex) { throw new Exception("encountered problem extracting data length string representation from XML", ex); } dataLength = 0; try { dataLength = int.Parse(dataLengthString, cult); } catch (System.Exception ex) { throw new Exception("encountered problem parsing data length from string representation " + (null != dataLengthString ? "\"" + dataLengthString + "\"" : "<>"), ex); } Array dataArray = null; try { dataArray = Array.CreateInstance(dataType, dataLength); } catch (System.Exception ex) { throw new Exception("encountered problem creating data array of type " + (null != dataType ? "\"" + dataType.FullName + "\"" : "<>") + " and length " + dataLength.ToString(), ex); } try { Values = (DataType[])dataArray; } catch (System.Exception ex) { throw new Exception("encountered problem assigning data array dynamically created from XML to Data.Values", ex); } } catch (System.Exception ex) { throw new Exception("encountered problem creating data array from XML", ex); } try { ScaleFactorMv = double.Parse(reader.GetAttribute(DataAdcToMvScaleFactorTag), cult); } catch (System.Exception ex) { throw new Exception("encountered problem parsing ADC->MV scaling factor property", ex); } try { MvPerEu = double.Parse(reader.GetAttribute(DataMvPerEuTag), cult); } catch (System.Exception ex) { throw new Exception("encountered problem parsing MV/EU sensitivity factor property", ex); } var dataTypeMembers = typeof(DataType).GetMember("Parse"); if (null == dataTypeMembers || dataTypeMembers.Length < 1) throw new Exception("data type does not contain a \"Parse\" method"); if (dataLength > 0) { Object dataTypeObject = null; try { dataTypeObject = Activator.CreateInstance(dataType); } catch (System.Exception ex) { throw new Exception("encountered problem creating an instance of type " + (null != dataType ? typeof(DataType).FullName : "<>"), ex); } var paramTypes = new Type[1]; paramTypes[0] = Type.GetType("System.String"); MethodInfo parseMethodInfo = null; try { parseMethodInfo = dataType.GetMethod("Parse", paramTypes); } catch (System.Exception ex) { throw new Exception("encountered problem getting \"Parse\" method information from data type " + dataType.FullName, ex); } for (var i = 0; i < Values.Length; i++) { reader.Read(); reader.MoveToContent(); string datumValueString = null; try { datumValueString = reader.GetAttribute(DatumValueXmlTag); } catch (System.Exception ex) { throw new Exception("encountered problem extracting datum value string representation from XML", ex); } var parameters = new Object[1]; parameters[0] = datumValueString; DataType parseResult; try { parseResult = (DataType)parseMethodInfo.Invoke(dataTypeObject, parameters); } catch (System.Exception ex) { throw new Exception("encountered problem invoking \"Parse\" method on string representation " + (datumValueString ?? "<>"), ex); } try { Values[i] = parseResult; } catch (System.Exception ex) { throw new Exception("encountered problem inserting parse result " + (null != parseResult ? parseResult.ToString() : "<>") + " into collection of data values", ex); } } } reader.Read(); reader.MoveToContent(); if (reader.Name.Equals(DataXmlTag, StringComparison.OrdinalIgnoreCase)) { // // This needs to be conditional in case we get inline data of length // zero. Though this probably will only ever happen under unit test. // reader.ReadEndElement(); // consume attribute end tag. reader.MoveToContent(); } } catch (System.Exception ex) { throw new Exception("encountered problem converting XML to DTS.Serialization.Test.Module.Channel.Data object", ex); } } /// /// Should normally return a schema representing the form of the XML /// generated/consumed by WriteXml/ReadXml, but it never called during /// the serialization process so ours just returns null. /// /// /// /// Null reference, always. /// /// public XmlSchema GetSchema() { // This method is never invoked during XML object serialization. return null; } /// /// Test the specified object for equality with this object. /// /// /// /// The to be tested for equality. /// /// /// /// true if the specified object has memeberwise equality with /// this object; false otherwise. /// /// public override bool Equals(object obj) { var that = obj as DataArray; try { return (null != that) && ScaleFactorMv.Equals(that.ScaleFactorMv) && MvPerEu.Equals(that.MvPerEu) && (Values.Length == that.Values.Length) && ValuesEquals(that.Values); } catch (System.Exception ex) { throw new Exception("encountered problem equality-testing object " + (null != obj ? "\"" + obj.ToString() + "\"" : "<>"), ex); } } /// /// Test the specified object's module list for equality with this object's /// data list. /// /// /// /// The of object to be /// compared for equality with this test's equivalent. /// /// /// /// true if the two lists contain equivalent-valued members; /// false otherwise. /// /// private bool ValuesEquals(DataType[] thoseValues) { try { if (null == thoseValues || Values.Length != thoseValues.Length) return false; for (var i = 0; i < Values.Length; i++) if (!Values[i].Equals(thoseValues[i])) return false; return true; } catch (System.Exception ex) { throw new Exception("encountered problem equality testing value array", ex); } } /// /// Return the hash code for this object. /// /// /// /// The hash code for this object. /// /// public override int GetHashCode() { return base.GetHashCode(); } } } } } }