/// <summary>Parse string using the specified value type and return the resulting variant.</summary> public static Variant Parse(VariantType valueType, string value) { if (string.IsNullOrEmpty(value)) { // Empty value return(new Variant()); } else { // Switch on type of default value switch (valueType) { case VariantType.String: return(new Variant(value)); case VariantType.Double: double doubleResult = double.Parse(value); return(new Variant(doubleResult)); case VariantType.Bool: bool boolResult = bool.Parse(value); return(new Variant(boolResult)); case VariantType.Int: int intResult = int.Parse(value); return(new Variant(intResult)); case VariantType.Long: long longResult = long.Parse(value); return(new Variant(longResult)); case VariantType.LocalDate: LocalDate dateResult = LocalDateUtil.Parse(value); return(new Variant(dateResult)); case VariantType.LocalTime: LocalTime timeResult = LocalTimeUtil.Parse(value); return(new Variant(timeResult)); case VariantType.LocalMinute: LocalMinute minuteResult = LocalMinuteUtil.Parse(value); return(new Variant(minuteResult)); case VariantType.LocalDateTime: LocalDateTime dateTimeResult = LocalDateTimeUtil.Parse(value); return(new Variant(dateTimeResult)); case VariantType.Instant: Instant instantResult = InstantUtil.Parse(value); return(new Variant(instantResult)); case VariantType.Enum: throw new Exception("Variant cannot be created as enum without specifying enum typename."); default: // Error message if any other type throw new Exception("Unknown value type when parsing string into variant."); } } }
/// <summary>Deserialize from data in ITreeReader.</summary> public void DeserializeFrom(ITreeReader reader) { // Do nothing if the selected XML node is empty if (reader == null) { return; } // Iterate over the list of elements var elementInfoList = DataTypeInfo.GetOrCreate(this).DataElements; foreach (var elementInfo in elementInfoList) { // Get element name and type string elementName = elementInfo.Name; Type elementType = elementInfo.PropertyType; // Get inner XML node, continue with next element if null ITreeReader innerXmlNode = reader.ReadElement(elementName); if (innerXmlNode == null) { continue; } // First check for each of the supported value types if (elementType == typeof(string)) { string token = innerXmlNode.ReadValue(); elementInfo.SetValue(this, token); } else if (elementType == typeof(double) || elementType == typeof(double?)) { string token = innerXmlNode.ReadValue(); var value = double.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(bool) || elementType == typeof(bool?)) { string token = innerXmlNode.ReadValue(); var value = bool.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(int) || elementType == typeof(int?)) { string token = innerXmlNode.ReadValue(); var value = int.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(long) || elementType == typeof(long?)) { string token = innerXmlNode.ReadValue(); var value = long.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(LocalDate) || elementType == typeof(LocalDate?)) { string token = innerXmlNode.ReadValue(); var value = LocalDateUtil.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(LocalTime) || elementType == typeof(LocalTime?)) { string token = innerXmlNode.ReadValue(); var value = LocalTimeUtil.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(LocalMinute) || elementType == typeof(LocalMinute?)) { string token = innerXmlNode.ReadValue(); var value = LocalMinuteUtil.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(LocalDateTime) || elementType == typeof(LocalDateTime?)) { string token = innerXmlNode.ReadValue(); var value = LocalDateTimeUtil.Parse(token); elementInfo.SetValue(this, value); } else if (elementType == typeof(Instant) || elementType == typeof(Instant?)) { string token = innerXmlNode.ReadValue(); var value = InstantUtil.Parse(token); elementInfo.SetValue(this, value); } else if (elementType.IsSubclassOf(typeof(Enum))) { string token = innerXmlNode.ReadValue(); var value = Enum.Parse(elementType, token); elementInfo.SetValue(this, value); } else { // If none of the supported atomic types match, use the activator // to create and empty instance of a complex type and populate it var element = Activator.CreateInstance(elementType); switch (element) { case IList listElement: listElement.DeserializeFrom(elementName, reader); break; case Data dataElement: var keyElement = dataElement as Key; if (keyElement != null) { // Deserialize key from value node containing semicolon delimited string string token = innerXmlNode.ReadValue(); // Parse semicolon delimited string to populate key elements keyElement.PopulateFrom(token); } else { // Deserialize embedded data object from the contents of inner XML node dataElement.DeserializeFrom(innerXmlNode); } break; case TemporalId idElement: // Do not serialize break; default: // Error message if the type does not match any of the value or reference types throw new Exception($"Serialization is not supported for type {elementType}."); } // Assign the populated key to the property elementInfo.SetValue(this, element); } } }
/// <summary>Parse string using the specified value type and return the resulting variant.</summary> public static Variant Parse <T>(string value) { if (string.IsNullOrEmpty(value)) { // Empty value return(new Variant()); } else { // Switch on type of default value switch (default(T)) { case string stringValue: return(new Variant(value)); case double doubleValue: double doubleResult = double.Parse(value); return(new Variant(doubleResult)); case bool boolValue: bool boolResult = bool.Parse(value); return(new Variant(boolResult)); case int intValue: int intResult = int.Parse(value); return(new Variant(intResult)); case long longValue: long longResult = long.Parse(value); return(new Variant(longResult)); case LocalDate dateValue: LocalDate dateResult = LocalDateUtil.Parse(value); return(new Variant(dateResult)); case LocalTime timeValue: LocalTime timeResult = LocalTimeUtil.Parse(value); return(new Variant(timeResult)); case LocalMinute minuteValue: LocalMinute minuteResult = LocalMinuteUtil.Parse(value); return(new Variant(minuteResult)); case LocalDateTime dateTimeValue: LocalDateTime dateTimeResult = LocalDateTimeUtil.Parse(value); return(new Variant(dateTimeResult)); case Instant instantValue: Instant instantResult = InstantUtil.Parse(value); return(new Variant(instantResult)); case Enum enumValue: object enumResult = Enum.Parse(typeof(T), value); return(new Variant(enumResult)); default: // Error message if any other type throw new Exception(GetWrongTypeErrorMessage(default(T))); } } }
/// <summary>Deserialize by reading element from the tree reader.</summary> public static void DeserializeFrom(this IList obj, string elementName, ITreeReader reader) { // Check if the list is null if (obj == null) { throw new Exception("List passed to DeserializeFrom method for element {elementName} is null."); } // If the list is not empty, error message because the // object must be empty prior to parsing if (obj.Count > 0) { throw new Exception("List passed to DeserializeFrom method for element {elementName} is not empty."); } // Get item type from list type using reflection Type listType = obj.GetType(); if (!listType.IsGenericType) { throw new Exception( $"Type {listType} cannot be serialized because it implements only IList but not IList<T>."); } Type[] genericParameterTypes = listType.GenericTypeArguments; if (genericParameterTypes.Length != 1) { throw new Exception( $"Generic parameter type list {genericParameterTypes} has more than " + $"one element creating an ambiguity for deserialization code."); } Type itemType = genericParameterTypes[0]; // Select XML node list with the specified name and iterate over XML nodes IEnumerable <ITreeReader> selectedXmlNodes = reader.ReadElements(elementName); foreach (ITreeReader selectedXmlNode in selectedXmlNodes) { if (selectedXmlNode == null) { // Add null value obj.Add(null); } else { // Switch on item type if (itemType == typeof(string)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { obj.Add(token); } else { obj.Add(null); } } else if (itemType == typeof(double) || itemType == typeof(double?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = double.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(bool) || itemType == typeof(bool?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = bool.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(int) || itemType == typeof(int?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = int.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(long) || itemType == typeof(long?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = long.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(LocalDate) || itemType == typeof(LocalDate?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = LocalDateUtil.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(LocalTime) || itemType == typeof(LocalTime?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = LocalTimeUtil.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(LocalMinute) || itemType == typeof(LocalMinute?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = LocalMinuteUtil.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(LocalDateTime) || itemType == typeof(LocalDateTime?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = LocalDateTimeUtil.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType == typeof(Instant) || itemType == typeof(Instant?)) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = InstantUtil.Parse(token); obj.Add(value); } else { obj.Add(null); } } else if (itemType.IsSubclassOf(typeof(Enum))) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { var value = Enum.Parse(itemType, token); obj.Add(value); } else { obj.Add(null); } } else { // If none of the supported atomic types match, use the activator // to create and empty instance of a complex type and populate it var item = Activator.CreateInstance(itemType); switch (item) { case ICollection collectionItem: throw new Exception($"Deserialization is not supported for element {elementName} " + $"which is collection containing another collection."); case Data dataItem: var keyItem = dataItem as Key; if (keyItem != null) { string token = selectedXmlNode.ReadValue(); if (!string.IsNullOrEmpty(token)) { // Parse semicolon delimited token to populate key item keyItem.PopulateFrom(token); obj.Add(item); } else { obj.Add(null); } } else { // Deserialize data item dataItem.DeserializeFrom(selectedXmlNode); obj.Add(item); } break; default: // Error message if the type does not match any of the value or reference types throw new Exception($"Serialization is not supported for type {itemType}."); } } } } }