private static SpecificationValue ParseSpecificationValue( XElement element, XmlSchema schema, XmlSchemaSet schemaSet, string ns) { SpecificationValue value; string isRef = GetRef(element, ns); if (isRef != null) { element.Validate( schema.SchemaTypes[new XmlQualifiedName("valueReference", ns)], schemaSet, (sender, args) => throw new ArgumentException(args.Message, args.Exception)); value = SpecificationValue.Ref(isRef); } else { SpecificationValue.Multiplicity mul = GetMul(element, ns); SpecificationValue.DataType type = GetType(element, ns); string[] values = GetValues(element, ns).ToArray(); if (values.Length <= 1) { element.Validate( schema.SchemaTypes[new XmlQualifiedName("valueSingle", ns)], schemaSet, (sender, args) => throw new ArgumentException(args.Message, args.Exception)); } else { element.Validate( schema.SchemaTypes[new XmlQualifiedName("valueMultiple", ns)], schemaSet, (sender, args) => throw new ArgumentException(args.Message, args.Exception)); } SpecificationValueSettings settings = ValueSettings.GetOrAdd( (int)mul * 1000 + (int)type, i => new SpecificationValueSettings { AllowCast = true, DefaultMultiplicity = mul, IncludeDetails = true, ExpectedType = type }); if (!SpecificationValue.TryFrom(values, settings, out value, out string error)) { throw new ArgumentException(error); } } return(value); }
public static bool TryFrom( string key, IReadOnlyDictionary <string, object> values, SpecificationValueSettings settings, out SpecificationValue result, out string error) { return(TryFrom(key, values, settings, new HashSet <SpecificationValue>(), out result, out error)); }
public static bool TryFrom(object value, SpecificationValueSettings settings, out SpecificationValue result, out string error) { error = null; result = null; if (value == null) { if (settings.IncludeDetails) { error = SpecAbsRes.SpecValueTryFromNull; } return(false); } Type type = value.GetType(); if (value is SpecificationValue sv) { result = sv; return(true); } if (TypeHelper.Mapping.ContainsKey(type)) { if (!settings.ExpectedType.HasValue || TypeHelper.Mapping[type] == settings.ExpectedType.Value) { result = Single(value); return(true); } if (TypeHelper.HasMappingOrCast(value, settings.ExpectedType.Value, settings, out object casted)) { result = Single(casted); return(true); } result = null; if (settings.IncludeDetails) { error = string.Format(SpecAbsRes.SpecValueAssumedTypeError, settings.ExpectedType.Value, value, type); } return(false); } if (value is IEnumerable en) { result = new SpecificationValue(); result.ValueMultiplicity = settings.DefaultMultiplicity; List <object> resultValues = new List <object>(5); int j = 0; foreach (object o in en) { if (o == null) { if (settings.IncludeDetails) { error = string.Format(SpecAbsRes.ValueSpecificationElementNull, j); } result = null; return(false); } j++; resultValues.Add(o); } if (resultValues.Count == 0) { if (settings.IncludeDetails) { error = SpecAbsRes.ValueSpecificationZeroCount; } result = null; return(false); } result.Values = resultValues; Type itemType = null; if (settings.ExpectedType.HasValue) { itemType = TypeHelper.Mapping.Single(p => p.Value == settings.ExpectedType.Value).Key; result.ValueType = settings.ExpectedType.Value; } for (int i = 0; i < resultValues.Count; i++) { Type currentType = resultValues[i].GetType(); if (itemType != null) { if (itemType != currentType) { if (TypeHelper.HasMappingOrCast(resultValues[i], result.ValueType, settings, out object casted)) { resultValues[i] = casted; currentType = casted.GetType(); } else { if (settings.IncludeDetails) { if (settings.ExpectedType.HasValue) { error = string.Format(SpecAbsRes.SpecValueAssumedTypeError, settings.ExpectedType.Value, resultValues[i], currentType); } else { error = SpecAbsRes.ValueSpecificationMixedTypes; } } result = null; return(false); } } } itemType = currentType; if (i == 0 && !settings.ExpectedType.HasValue) { if (TypeHelper.Mapping.ContainsKey(itemType)) { result.ValueType = TypeHelper.Mapping[itemType]; } else { if (settings.IncludeDetails) { error = string.Format( SpecAbsRes.SpecificationValueTypeNotSupportedElement, itemType, i, string.Join(", ", TypeHelper.Mapping.Keys)); } result = null; return(false); } } } return(true); } if (settings.IncludeDetails) { error = string.Format( SpecAbsRes.SpecificationValueTypeNotSupported, type, string.Join(", ", TypeHelper.Mapping.Keys)); } return(false); }
private static bool TryFrom( string key, IReadOnlyDictionary <string, object> values, SpecificationValueSettings settings, HashSet <SpecificationValue> processed, out SpecificationValue result, out string error) { result = null; error = null; if (key == null) { throw new ArgumentNullException(nameof(key)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (settings == null) { throw new ArgumentNullException(nameof(settings)); } if (processed == null) { throw new ArgumentNullException(nameof(processed)); } if (values.ContainsKey(key)) { object value = values[key]; if (TryFrom(value, settings, out result, out error)) { if (result.IsReference) { if (processed.Contains(result)) { if (settings.IncludeDetails) { processed.Add(result); // Add to display correct message error = SpecAbsRes.SpecValueFromCircular + string.Format( SpecAbsRes.SpecValueFromProcessed, string.Join(", ", processed)); } result = null; return(false); } processed.Add(result); string next = result.Values.Single().ToString(); bool tryNext = TryFrom(next, values, settings, processed, out var nextResult, out error); if (tryNext) { result = nextResult; } return(tryNext); } return(true); } if (settings.IncludeDetails && processed.Any()) { error += string.Format(SpecAbsRes.SpecValueFromProcessed, string.Join(", ", processed)); } return(false); } if (settings.IncludeDetails) { error = string.Format(SpecAbsRes.KeyValueSpecificationMissingKey, key); if (processed.Any()) { error += string.Format( SpecAbsRes.SpecValueFromProcessed, string.Join(", ", processed)); } } return(false); }
public static bool HasMappingOrCast( object value, SpecificationValue.DataType desiredType, SpecificationValueSettings settings, out object result) { result = value; if (value == null) { return(false); } Type type = value.GetType(); if (Mapping.ContainsKey(type)) { SpecificationValue.DataType actualType = Mapping[type]; if (actualType == desiredType) { return(true); } } if (settings.AllowCast) { switch (desiredType) { case SpecificationValue.DataType.DateTime: { if (value is string str) { if (DateTime.TryParseExact( str, "u", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime dtv)) { result = dtv; return(true); } } } break; case SpecificationValue.DataType.Int: { if (value is float fv && Math.Round(fv) == fv) { result = (int)fv; return(true); } if (value is string str) { if (int.TryParse(str, out int iv)) { result = iv; return(true); } } } break; case SpecificationValue.DataType.Float: { if (value is int iv) { result = (float)iv; return(true); } if (value is string str) { if (float.TryParse(str, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out float fv)) { result = fv; return(true); } } } break; case SpecificationValue.DataType.String: { if (value is int iv) { result = iv.ToString("D"); } else if (value is float fv) { result = fv.ToString("F"); } else if (value is DateTime dtv) { result = dtv.ToString("u"); } else { result = value.ToString(); } return(true); } default: return(false); } } return(false); }