-
Notifications
You must be signed in to change notification settings - Fork 400
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
Changes from all commits
d3bdd17
5283caf
3317a49
7d3f110
4673c9a
21c2f84
dc69270
04f233c
b9d895d
File filter
Filter by extension
Conversations
Jump to
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() | ||
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)); | ||
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. 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? 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.
Show resolved
Hide resolved
|
||
if(quantityType == null) | ||
return false; | ||
|
||
return true; | ||
return quantityType != null; | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.