Skip to content

Commit

Permalink
Merge pull request #496 from angularsen/v4-remove-unitsystem-static
Browse files Browse the repository at this point in the history
Remove UnitSystem static methods
  • Loading branch information
tmilnthorp authored Oct 1, 2018
2 parents cece5fb + 0e3dba3 commit 0aab57b
Showing 1 changed file with 79 additions and 36 deletions.
115 changes: 79 additions & 36 deletions UnitsNet/CustomCode/UnitSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,26 @@
// ReSharper disable once CheckNamespace
namespace UnitsNet
{
/// <summary>
/// Main facade for working with units dynamically and configuring default behavior for quantities' ToString():
/// - Instance per culture via <see cref="GetCached(System.IFormatProvider)"/>, for caching number formatting and unit abbreviation localization
/// - Use <see cref="Default"/> for local system's current culture
/// - Override <see cref="DefaultCulture"/> to affect number formatting and localization of all quantities' ToString() when culture is not specified
/// - <see cref="Parse"/> unit abbreviations with dynamic types
/// - Dynamically add abbreviations to unit enums with <see cref="MapUnitToAbbreviation"/>
/// </summary>
[PublicAPI]
public sealed partial class UnitSystem
{
private static readonly Dictionary<IFormatProvider, UnitSystem> CultureToInstance;

/// <summary>
/// Fallback culture used by <see cref="GetAllAbbreviations{TUnitType}" /> and
/// <see cref="GetDefaultAbbreviation{TUnitType}(TUnitType,CultureInfo)" />
/// <see cref="GetDefaultAbbreviation{TUnitType}" />
/// if no abbreviations are found with current <see cref="Culture" />.
/// </summary>
/// <example>
/// User wants to call <see cref="Parse{TUnitType}(string,System.IFormatProvider)" /> or <see cref="object.ToString" /> with Russian
/// User wants to call <see cref="Parse{TUnitType}" /> or <see cref="Length.ToString()" /> with Russian
/// culture, but no translation is defined, so we return the US English definition as a last resort. If it's not
/// defined there either, an exception is thrown.
/// </example>
Expand Down Expand Up @@ -147,8 +155,15 @@ public UnitSystem() : this(DefaultCulture)
#endif
static IFormatProvider DefaultCulture { get; set; } = CultureInfo.CurrentUICulture;

public bool IsFallbackCulture => Culture.Equals(FallbackCulture);
/// <summary>
/// Whether this instance is for the <see cref="FallbackCulture"/>.
/// </summary>
private bool IsFallbackCulture => Culture.Equals(FallbackCulture);

/// <summary>
/// Clear the cached singleton instances.
/// Calling <see cref="Default"/> or <see cref="GetCached(string)"/> afterwards will create a new instance.
/// </summary>
[PublicAPI]
public static void ClearCache()
{
Expand Down Expand Up @@ -185,6 +200,11 @@ public static UnitSystem GetCached([CanBeNull] string cultureName)
}

// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
/// <summary>
/// Gets or creates the singleton instance configured with localized unit abbreviations and number formatting for the given culture.
/// </summary>
/// <param name="cultureInfo">The culture.</param>
/// <returns>The instance.</returns>
#if WINDOWS_UWP
internal
#else
Expand All @@ -205,19 +225,13 @@ static UnitSystem GetCached([CanBeNull] IFormatProvider cultureInfo)
}
}

[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
internal
#else
public
#endif
static TUnitType Parse<TUnitType>(string unitAbbreviation, IFormatProvider culture)
where TUnitType : /*Enum constraint hack*/ struct, IComparable, IFormattable
{
return GetCached(culture).Parse<TUnitType>(unitAbbreviation);
}

/// <summary>
/// Parses a unit abbreviation for a given unit enumeration type.
/// Example: Parse&lt;LengthUnit&gt;("km") => LengthUnit.Kilometer
/// </summary>
/// <param name="unitAbbreviation"></param>
/// <typeparam name="TUnitType"></typeparam>
/// <returns></returns>
[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
Expand Down Expand Up @@ -246,12 +260,10 @@ TUnitType Parse<TUnitType>(string unitAbbreviation)
[PublicAPI]
public object Parse(string unitAbbreviation, Type unitType)
{
AbbreviationMap abbrevToUnitValue;
if (!_unitTypeToAbbrevToUnitValue.TryGetValue(unitType, out abbrevToUnitValue))
if (!_unitTypeToAbbrevToUnitValue.TryGetValue(unitType, out var abbrevToUnitValue))
throw new UnitNotFoundException($"No abbreviations defined for unit type [{unitType}] for culture [{Culture}].");

List<int> unitIntValues;
List<object> unitValues = abbrevToUnitValue.TryGetValue(unitAbbreviation, out unitIntValues)
List<object> unitValues = abbrevToUnitValue.TryGetValue(unitAbbreviation, out var unitIntValues)
? unitIntValues.Distinct().Cast<object>().ToList()
: new List<object>();

Expand All @@ -268,19 +280,13 @@ public object Parse(string unitAbbreviation, Type unitType)
}
}

[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
internal
#else
public
#endif
static string GetDefaultAbbreviation<TUnitType>(TUnitType unit, CultureInfo culture)
where TUnitType : /*Enum constraint hack*/ struct, IComparable, IFormattable
{
return GetCached(culture).GetDefaultAbbreviation(unit);
}

/// <summary>
/// Gets the default abbreviation for a given unit. If a unit has more than one abbreviation defined, then it returns the first one.
/// Example: GetDefaultAbbreviation&lt;LengthUnit&gt;(LengthUnit.Kilometer) => "km"
/// </summary>
/// <param name="unit">The unit enum value.</param>
/// <typeparam name="TUnitType">The type of unit enum.</typeparam>
/// <returns>The default unit abbreviation string.</returns>
[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
Expand All @@ -294,12 +300,28 @@ string GetDefaultAbbreviation<TUnitType>(TUnitType unit)
return GetAllAbbreviations(unit).First();
}

/// <summary>
/// Gets the default abbreviation for a given unit type and its numeric enum value.
/// If a unit has more than one abbreviation defined, then it returns the first one.
/// Example: GetDefaultAbbreviation&lt;LengthUnit&gt;(typeof(LengthUnit), 1) => "cm"
/// </summary>
/// <param name="unitType">The unit enum type.</param>
/// <param name="unitValue">The unit enum value.</param>
/// <returns>The default unit abbreviation string.</returns>
[PublicAPI]
public string GetDefaultAbbreviation(Type unitType, int unitValue)
{
return GetAllAbbreviations(unitType, unitValue).First();
}

/// <summary>
/// Adds one or more unit abbreviation for the given unit enum value.
/// This is used to dynamically add abbreviations for existing unit enums such as <see cref="LengthUnit"/> or to extend with third-party unit enums
/// in order to <see cref="Parse{TUnitType}"/> or <see cref="GetDefaultAbbreviation{TUnitType}"/> on them later.
/// </summary>
/// <param name="unit">The unit enum value.</param>
/// <param name="abbreviations">Unit abbreviations to add.</param>
/// <typeparam name="TUnitType">The type of unit enum.</typeparam>
[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
Expand All @@ -318,6 +340,14 @@ void MapUnitToAbbreviation<TUnitType>(TUnitType unit, params string[] abbreviati
MapUnitToAbbreviation(unitType, unitValue, abbreviations);
}

/// <summary>
/// Adds one or more unit abbreviation for the given unit enum value.
/// This is used to dynamically add abbreviations for existing unit enums such as <see cref="LengthUnit"/> or to extend with third-party unit enums
/// in order to <see cref="Parse{TUnitType}"/> or <see cref="GetDefaultAbbreviation{TUnitType}"/> on them later.
/// </summary>
/// <param name="unitType">The unit enum type.</param>
/// <param name="unitValue">The unit enum value.</param>
/// <param name="abbreviations">Unit abbreviations to add.</param>
[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
Expand Down Expand Up @@ -364,6 +394,13 @@ void MapUnitToAbbreviation(Type unitType, int unitValue, [NotNull] params string
}
}

/// <summary>
/// Try to parse a unit abbreviation.
/// </summary>
/// <param name="unitAbbreviation">The string value.</param>
/// <param name="unit">The unit enum value as out result.</param>
/// <typeparam name="TUnitType">Type of unit enum.</typeparam>
/// <returns>True if successful.</returns>
[PublicAPI]
// Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
#if WINDOWS_UWP
Expand All @@ -386,6 +423,13 @@ bool TryParse<TUnitType>(string unitAbbreviation, out TUnitType unit)
}
}

/// <summary>
/// Try to parse a unit abbreviation.
/// </summary>
/// <param name="unitAbbreviation">The string value.</param>
/// <param name="unitType">Type of unit enum.</param>
/// <param name="unit">The unit enum value as out result.</param>
/// <returns>True if successful.</returns>
[PublicAPI]
public bool TryParse(string unitAbbreviation, Type unitType, out object unit)
{
Expand Down Expand Up @@ -484,12 +528,11 @@ private void LoadDefaultAbbreviations([NotNull] IFormatProvider culture)
foreach (CulturesForEnumValue ev in localization.EnumValues)
{
int unitEnumValue = ev.Value;
var usCulture = new CultureInfo("en-US");

// Fall back to US English if localization not found
AbbreviationsForCulture matchingCulture =
var matchingCulture =
ev.Cultures.FirstOrDefault(a => a.Cult.Equals(culture)) ??
ev.Cultures.FirstOrDefault(a => a.Cult.Equals(usCulture));
ev.Cultures.FirstOrDefault(a => a.Cult.Equals(FallbackCulture));

if (matchingCulture == null)
continue;
Expand Down

0 comments on commit 0aab57b

Please sign in to comment.