internal static bool TryParse <T, MEASUREMENT>(string @string, out MEASUREMENT measurement, Symbolics.TryParseNumeric <T> tryParseNumeric = null) { if (!TryParse(@string, out object parsedMeasurment, tryParseNumeric) || !(parsedMeasurment is MEASUREMENT)) { measurement = default; return(false); } measurement = (MEASUREMENT)parsedMeasurment; return(true); }
/// <summary>Parses a measurement from a string.</summary> /// <typeparam name="T">The numeric type to parse the quantity as.</typeparam> /// <param name="string">The string to parse.</param> /// <param name="measurement">The parsed measurement if successful or default if unsuccessful.</param> /// <param name="tryParseNumeric">Explicit try parse function for the numeric type.</param> /// <returns>True if successful or false if not.</returns> public static bool TryParse <T>(string @string, out object measurement, Symbolics.TryParseNumeric <T> tryParseNumeric = null) { if (!ParsingLibraryBuilt) { BuildParsingLibrary(); } if (!TypeSpecificParsingLibrary <T> .TypeSpecificParsingLibraryBuilt) { TypeSpecificParsingLibrary <T> .BuildTypeSpecificParsingLibrary(); } List <object> parameters = new List <object>(); bool AtLeastOneUnit = false; bool? numerator = null; MatchCollection matchCollection = Regex.Matches(@string, AllUnitsRegexPattern); if (matchCollection.Count <= 0 || matchCollection[0].Index <= 0) { measurement = default; return(false); } string numericString = @string.Substring(0, matchCollection[0].Index); T value; try { value = Symbolics.ParseAndSimplifyToConstant <T>(numericString, tryParseNumeric); } catch { measurement = default; return(false); } StringBuilder stringBuilder = new StringBuilder(); foreach (Match match in matchCollection) { string matchValue = match.Value; if (matchValue.Equals("*") || matchValue.Equals("/")) { if (!(numerator is null)) { measurement = default; return(false); } if (!AtLeastOneUnit) { measurement = default; return(false); } numerator = matchValue.Equals("*"); continue; } if (!UnitStringToEnumMap.TryGetValue(match.Value, out Enum @enum)) { measurement = default; return(false); } if (!AtLeastOneUnit) { if (!(numerator is null)) { measurement = default; return(false); } AtLeastOneUnit = true; stringBuilder.Append(@enum.GetType().DeclaringType.Name); parameters.Add(@enum); } else { if (numerator is null) { measurement = default; return(false); } if (numerator.Value) { stringBuilder.Append("*" + @enum.GetType().DeclaringType.Name); parameters.Add(@enum); } else { stringBuilder.Append("/" + @enum.GetType().DeclaringType.Name); parameters.Add(@enum); } } numerator = null; } if (!(numerator is null)) { measurement = default; return(false); } string key = stringBuilder.ToString(); Func <T, object[], object> factory = TypeSpecificParsingLibrary <T> .UnitsStringsToFactoryFunctions[key]; measurement = factory(value, parameters.ToArray()); return(true); }