diff --git a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs index 5103231a36..5e83ae4d67 100644 --- a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs +++ b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs @@ -296,6 +296,28 @@ public void MapUnitToDefaultAbbreviation_GivenCustomAbbreviation_SetsAbbreviatio Assert.Equal("1 m^2", Area.FromSquareMeters(1).ToString(newZealandCulture)); } + [Fact] + public void MapUnitToDefaultAbbreviation_ParsesUsingDefaultString() + { + var cache = new UnitAbbreviationsCache(); + cache.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); + + var parser = new QuantityParser(cache); + Assert.Equal(MassFlow.FromPoundsPerSecond(10), parser.Parse("10 lb/s", NorwegianCulture, MassFlow.From)); + } + + [Fact] + public void MapUnitToDefaultAbbreviation_AddsNewUnitAsAdditionalOverride() + { + var cache = new UnitAbbreviationsCache(); + var abbreviationsBefore = cache.GetUnitAbbreviations(MassFlowUnit.GramPerSecond, NorwegianCulture); + + cache.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); + + var abbreviationsAfter = cache.GetUnitAbbreviations(MassFlowUnit.GramPerSecond, NorwegianCulture); + Assert.Equal(abbreviationsBefore.Length + 1, abbreviationsAfter.Length); + } + /// /// Convenience method to the proper culture parameter type. /// diff --git a/UnitsNet/CustomCode/UnitAbbreviationsCache.cs b/UnitsNet/CustomCode/UnitAbbreviationsCache.cs index a0b52ff101..dbb84304de 100644 --- a/UnitsNet/CustomCode/UnitAbbreviationsCache.cs +++ b/UnitsNet/CustomCode/UnitAbbreviationsCache.cs @@ -276,9 +276,11 @@ public string[] GetUnitAbbreviations(Type unitType, int unitValue, IFormatProvid if(!TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var lookup)) return formatProvider != FallbackCulture ? GetUnitAbbreviations(unitType, unitValue, FallbackCulture) : new string[] { }; - var abbreviations = lookup!.GetAbbreviationsForUnit(unitValue); - if(abbreviations.Count == 0) - return formatProvider != FallbackCulture ? GetUnitAbbreviations(unitType, unitValue, FallbackCulture) : new string[] { }; + var abbreviations = new HashSet(); + abbreviations.UnionWith(lookup!.GetAbbreviationsForUnit(unitValue)); + + if(formatProvider != FallbackCulture) + abbreviations.UnionWith(GetUnitAbbreviations(unitType, unitValue, FallbackCulture)); return abbreviations.ToArray(); } @@ -297,10 +299,32 @@ public string[] GetAllUnitAbbreviationsForQuantity(Type unitEnumType, IFormatPro if(!TryGetUnitValueAbbreviationLookup(unitEnumType, formatProvider, out var lookup)) return formatProvider != FallbackCulture ? GetAllUnitAbbreviationsForQuantity(unitEnumType, FallbackCulture) : new string[] { }; - return lookup!.GetAllUnitAbbreviationsForQuantity(); + var allAbbreviations = new HashSet(); + allAbbreviations.UnionWith(lookup!.GetAllUnitAbbreviationsForQuantity()); + + if(formatProvider != FallbackCulture) + allAbbreviations.UnionWith(GetAllUnitAbbreviationsForQuantity(unitEnumType, FallbackCulture)); + + return allAbbreviations.ToArray(); + } + + internal List GetUnitsForAbbreviation(Type unitType, IFormatProvider? formatProvider, string abbreviation, bool ignoreCase) + { + formatProvider = formatProvider ?? CultureInfo.CurrentUICulture; + + if(!TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var lookup)) + return formatProvider != FallbackCulture ? GetUnitsForAbbreviation(unitType, FallbackCulture, abbreviation, ignoreCase) : new List(); + + var units = new HashSet(); + units.UnionWith(lookup!.GetUnitsForAbbreviation(abbreviation, ignoreCase)); + + if(formatProvider != FallbackCulture) + units.UnionWith(GetUnitsForAbbreviation(unitType, FallbackCulture, abbreviation, ignoreCase)); + + return units.ToList(); } - internal bool TryGetUnitValueAbbreviationLookup(Type unitType, IFormatProvider? formatProvider, out UnitValueAbbreviationLookup? unitToAbbreviations) + private bool TryGetUnitValueAbbreviationLookup(Type unitType, IFormatProvider? formatProvider, out UnitValueAbbreviationLookup? unitToAbbreviations) { unitToAbbreviations = null; diff --git a/UnitsNet/CustomCode/UnitParser.cs b/UnitsNet/CustomCode/UnitParser.cs index 2becb1fd4d..9e8f95bcae 100644 --- a/UnitsNet/CustomCode/UnitParser.cs +++ b/UnitsNet/CustomCode/UnitParser.cs @@ -72,20 +72,17 @@ public Enum Parse([NotNull] string unitAbbreviation, Type unitType, IFormatProvi if (unitAbbreviation == null) throw new ArgumentNullException(nameof(unitAbbreviation)); unitAbbreviation = unitAbbreviation.Trim(); - if(!_unitAbbreviationsCache.TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var abbreviations)) - throw new UnitNotFoundException($"No abbreviations defined for unit type [{unitType}] for culture [{formatProvider}]."); - - var unitIntValues = abbreviations!.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + var unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); if (unitIntValues.Count == 0) { unitAbbreviation = NormalizeUnitString(unitAbbreviation); - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); } // Narrow the search if too many hits, for example Megabar "Mbar" and Millibar "mbar" need to be distinguished if (unitIntValues.Count > 1) - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: false); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: false); switch (unitIntValues.Count) { @@ -197,20 +194,17 @@ public bool TryParse(string? unitAbbreviation, Type unitType, IFormatProvider? f unitAbbreviation = unitAbbreviation.Trim(); unit = default; - if(!_unitAbbreviationsCache.TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var abbreviations)) - return false; - - var unitIntValues = abbreviations!.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + var unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); if (unitIntValues.Count == 0) { unitAbbreviation = NormalizeUnitString(unitAbbreviation); - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); } // Narrow the search if too many hits, for example Megabar "Mbar" and Millibar "mbar" need to be distinguished if (unitIntValues.Count > 1) - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: false); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: false); if(unitIntValues.Count != 1) return false; diff --git a/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs b/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs index a82d3f7faf..089770606a 100644 --- a/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs +++ b/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs @@ -73,7 +73,6 @@ internal void Add(int unit, string abbreviation, bool setAsDefault = false) abbreviationsForUnit.Insert(0, abbreviation); else abbreviationsForUnit.Add(abbreviation); - } } }