-
Notifications
You must be signed in to change notification settings - Fork 386
Extending with Custom Units
Andreas Gullberg Larsen edited this page Oct 14, 2020
·
20 revisions
This article is for when you want to add your own custom units and quantities in your code, to represent as IQuantity
and to reuse Units.NET for parsing and converting between units.
If you are looking to add new quantities or units to the UnitsNet
nuget, please see https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit.
Units.NET roughly consists of these parts:
- Quantities like
Length
andForce
- Unit enum values like
LengthUnit.Meter
andForceUnit.Newton
-
UnitAbbreviationsCache
,UnitParser
,QuantityParser
andUnitConverter
for parsing and converting quantities and units - JSON files for defining units, conversion functions and abbreviations
- CodeGen.exe to generate C# code based on JSON files
GetDefaultAbbreviation(): sm, lts, tns
Parse<HowMuchUnit>(): Some, Lots, Tons
Convert 10 tons to:
200 sm
100 lts
10 tns
UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(HowMuchUnit.Some, "sm");
UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(HowMuchUnit.Lots, "lts");
UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(HowMuchUnit.Tons, "tns");
Console.WriteLine("GetDefaultAbbreviation(): " + string.Join(", ",
UnitAbbreviationsCache.Default.GetDefaultAbbreviation(HowMuchUnit.Some), // "sm"
UnitAbbreviationsCache.Default.GetDefaultAbbreviation(HowMuchUnit.Lots), // "lts"
UnitAbbreviationsCache.Default.GetDefaultAbbreviation(HowMuchUnit.Tons) // "tns"
));
Console.WriteLine("Parse<HowMuchUnit>(): " + string.Join(", ",
UnitParser.Default.Parse<HowMuchUnit>("sm"), // Some
UnitParser.Default.Parse<HowMuchUnit>("lts"), // Lots
UnitParser.Default.Parse<HowMuchUnit>("tns") // Tons
));
var unitConverter = UnitConverter.Default;
unitConverter.SetConversionFunction<HowMuch>(HowMuchUnit.Lots, HowMuchUnit.Some, x => new HowMuch(x.Value * 2, HowMuchUnit.Some));
unitConverter.SetConversionFunction<HowMuch>(HowMuchUnit.Tons, HowMuchUnit.Lots, x => new HowMuch(x.Value * 10, HowMuchUnit.Lots));
unitConverter.SetConversionFunction<HowMuch>(HowMuchUnit.Tons, HowMuchUnit.Some, x => new HowMuch(x.Value * 20, HowMuchUnit.Some));
var from = new HowMuch(10, HowMuchUnit.Tons);
IQuantity Convert(HowMuchUnit toUnit) => unitConverter.GetConversionFunction<HowMuch>(from.Unit, toUnit)(from);
Console.WriteLine($"Convert 10 tons to:");
Console.WriteLine(Convert(HowMuchUnit.Some)); // 200 sm
Console.WriteLine(Convert(HowMuchUnit.Lots)); // 100 lts
Console.WriteLine(Convert(HowMuchUnit.Tons)); // 10 tns
https://github.com/angularsen/UnitsNet/blob/master/UnitsNet.Tests/CustomQuantities/HowMuchUnit.cs
https://github.com/angularsen/UnitsNet/blob/master/UnitsNet.Tests/CustomQuantities/HowMuch.cs
public enum HowMuchUnit
{
Some,
Lots,
Tons
}
public struct HowMuch : IQuantity
{
public HowMuch(double value, HowMuchUnit unit)
{
Unit = unit;
Value = value;
}
Enum IQuantity.Unit => Unit;
public HowMuchUnit Unit { get; }
public double Value { get; }
#region IQuantity
private static readonly HowMuch Zero = new HowMuch(0, HowMuchUnit.Some);
public QuantityType Type => QuantityType.Undefined;
public BaseDimensions Dimensions => BaseDimensions.Dimensionless;
public QuantityInfo QuantityInfo => new QuantityInfo(Type,
new UnitInfo[]
{
new UnitInfo<HowMuchUnit>(HowMuchUnit.Some, BaseUnits.Undefined),
new UnitInfo<HowMuchUnit>(HowMuchUnit.Lots, BaseUnits.Undefined),
new UnitInfo<HowMuchUnit>(HowMuchUnit.Tons, BaseUnits.Undefined),
},
HowMuchUnit.Some,
Zero,
BaseDimensions.Dimensionless);
public double As(Enum unit) => Convert.ToDouble(unit);
public double As(UnitSystem unitSystem) => throw new NotImplementedException();
public IQuantity ToUnit(Enum unit)
{
if (unit is HowMuchUnit howMuchUnit) return new HowMuch(As(unit), howMuchUnit);
throw new ArgumentException("Must be of type HowMuchUnit.", nameof(unit));
}
public IQuantity ToUnit(UnitSystem unitSystem) => throw new NotImplementedException();
public override string ToString() => $"{Value} {UnitAbbreviationsCache.Default.GetDefaultAbbreviation(Unit)}";
public string ToString(string format, IFormatProvider formatProvider) => $"HowMuch ({format}, {formatProvider})";
public string ToString(IFormatProvider provider) => $"HowMuch ({provider})";
public string ToString(IFormatProvider provider, int significantDigitsAfterRadix) => $"HowMuch ({provider}, {significantDigitsAfterRadix})";
public string ToString(IFormatProvider provider, string format, params object[] args) => $"HowMuch ({provider}, {string.Join(", ", args)})";
#endregion
}