- Notifications
You must be signed in to change notification settings - Fork 416
Case insensitive unit parsing and conversion.#584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
d3bdd175283caf3317a497d3f1104673c9a21c2f84dc6927004f233cb9d895dFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -40,10 +40,18 @@ namespace UnitsNet | ||
| /// </summary> | ||
| public static class UnitConverter | ||
| { | ||
| private static readonly string QuantityNamespace = typeof(Length).Namespace; | ||
| private static readonly string UnitTypeNamespace = typeof(LengthUnit).Namespace; | ||
| private static readonly Assembly UnitsNetAssembly = typeof(Length).GetAssembly(); | ||
| private static readonly Type[] QuantityTypes = UnitsNetAssembly.GetTypes() | ||
Owner There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These include a lot more types than just the quantity structs and the unit enums. | ||
| .Where(typeof(IQuantity).IsAssignableFrom) | ||
| .Where(x => x.IsClass() || x.IsValueType()) // Future-proofing: we are discussing changing quantities from struct to class | ||
| .ToArray(); | ||
| private static readonly Type[] UnitTypes = UnitsNetAssembly.GetTypes() | ||
| .Where(x => x.Namespace == UnitTypeNamespace && x.IsEnum() && x.Name.EndsWith("Unit")) | ||
| .ToArray(); | ||
| /// <summary> | ||
| /// Convert between any two quantity units by their names, such as converting a "Length" of N "Meter" to "Centimeter". | ||
| /// This is particularly useful for creating things like a generated unit conversion UI, | ||
| @@ -72,7 +80,7 @@ public static class UnitConverter | ||
| /// <returns>Output value as the result of converting to <paramref name="toUnit" />.</returns> | ||
| /// <exception cref="QuantityNotFoundException">No quantities were found that match <paramref name="quantityName" />.</exception> | ||
| /// <exception cref="UnitNotFoundException">No units match the abbreviation.</exception> | ||
| /// <exception cref="AmbiguousUnitParseException">More than one unit matches the abbrevation.</exception> | ||
| /// <exception cref="AmbiguousUnitParseException">More than one unit matches the abbreviation.</exception> | ||
| public static double ConvertByName(FromValue fromValue, string quantityName, string fromUnit, string toUnit) | ||
| { | ||
| if(!TryGetQuantityType(quantityName, out var quantityType)) | ||
| @@ -219,7 +227,7 @@ public static double ConvertByAbbreviation(FromValue fromValue, string quantityN | ||
| /// <returns>Output value as the result of converting to <paramref name="toUnitAbbrev" />.</returns> | ||
| /// <exception cref="QuantityNotFoundException">No quantity types match the <paramref name="quantityName"/>.</exception> | ||
| /// <exception cref="UnitNotFoundException">No unit types match the prefix of <paramref name="quantityName"/> or no units are mapped to the abbreviation.</exception> | ||
| /// <exception cref="AmbiguousUnitParseException">More than one unit matches the abbrevation.</exception> | ||
| /// <exception cref="AmbiguousUnitParseException">More than one unit matches the abbreviation.</exception> | ||
| public static double ConvertByAbbreviation(FromValue fromValue, string quantityName, string fromUnitAbbrev, string toUnitAbbrev, string culture) | ||
| { | ||
| if(!TryGetQuantityType(quantityName, out var quantityType)) | ||
| @@ -384,37 +392,30 @@ private static bool HasParameterTypes(MethodInfo methodInfo, params Type[] expec | ||
| private static bool TryParseUnit(Type unitType, string unitName, out object unitValue) | ||
| { | ||
| unitValue = null; | ||
| if(!Enum.IsDefined(unitType, unitName)) | ||
| var eNames = Enum.GetNames(unitType); | ||
| unitName = eNames.FirstOrDefault(x => x.Equals(unitName, StringComparison.OrdinalIgnoreCase)); | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably use Enum.TryParse which includes a bool parameter to specify ignoring case. See here. ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would also prefer this method, but I can't use that here without using reflection, which I was trying to avoid. The try parse method you linked takes a generic type argument, which means that the type has to be known at compile type. We have a Type parameter known only at run time. Is there another TryParse that you know of that takes the enum type "Type" as parameter? Owner There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
| ||
| if(unitName == null) | ||
| return false; | ||
| unitValue = Enum.Parse(unitType, unitName); | ||
| if(unitValue == null) | ||
| return false; | ||
| return true; | ||
| } | ||
| private static bool TryGetUnitType(string quantityName, out Type unitType) | ||
| { | ||
| string unitTypeName = $"{UnitTypeNamespace}.{quantityName}Unit"; | ||
| var unitTypeName = quantityName + "Unit"; // ex. LengthUnit | ||
| unitType = UnitsNetAssembly.GetType(unitTypeName); // ex: UnitsNet.Units.LengthUnit enum | ||
| if(unitType == null) | ||
| return false; | ||
| unitType = UnitTypes.FirstOrDefault(x => | ||
| x.Name.Equals(unitTypeName, StringComparison.OrdinalIgnoreCase)); | ||
| return true; | ||
| return unitType != null; | ||
| } | ||
| private static bool TryGetQuantityType(string quantityName, out Type quantityType) | ||
| { | ||
| string quantityTypeName = $"{QuantityNamespace}.{quantityName}"; | ||
| quantityType = QuantityTypes.FirstOrDefault(x => x.Name.Equals(quantityName, StringComparison.OrdinalIgnoreCase)); | ||
| quantityType = UnitsNetAssembly.GetType(quantityTypeName); // ex: UnitsNet.Length struct | ||
TrevorVonSeggern marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if(quantityType == null) | ||
| return false; | ||
| return true; | ||
| return quantityType != null; | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.