Skip to content

Extending with Custom Units

Andreas Gullberg Larsen edited this page Mar 2, 2018 · 20 revisions

This page is about extending with CUSTOM units, which means quantities and units that are not part of the official build. This scenario is not well supported and not well thought out, so consider this page rambling early thoughts as base for future discussion.

If you are looking to add new quantities or units to the official UnitsNet nuget, please see https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit.

Units.NET structure

Units.NET roughly consists of these parts:

  • Quantities, like Length and Force
  • Unit enum values, like LengthUnit.Meter and ForceUnit.Newton
  • UnitSystem for looking up unit abbreviations and unit enums in various cultures, used by ToString() and Parse() in unit classes
  • JSON files for defining units, conversion functions and abbreviations
  • Powershell scripts for generating unit classes, unit enums and test code stubs

What does extending with custom units even mean?

At this point, I'm not really sure! :-)

What I can think of is:

Reuse the code generator scripts for new quantities

Let's say MagicMass is a special kind of mass that the official library does not want to add, because it is too esoteric. It has the units MagicKilogram and MagicTonne and you want to generate your own struct MagicMass type with with all the unit conversion code, parsing, ToString() and so on that you are used to in Units.NET.

I'm not sure what the exact steps are, but you would probably create this as a new library and copy in all the scripts and JSON files and modify these to your needs. For instance, you would probably want a different namespace and you probably don't want to duplicate the core code such as UnitSystem so you would have to strip out a lot of the stuff that already exists in UnitsNet. If you want to start from scratch and not have a dependency on UnitsNet, you could keep most of the code as-is.

Add unit enum types at runtime and reuse for ToString() and Parse()

You can achieve this with something like this:

CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US");
UnitSystem unitSystem = UnitSystem.GetCached(cultureInfo);
unitSystem.MapUnitToAbbreviation(FooUnit.Bar, "bar");

Assert.AreEqual("bar", unitSystem.GetDefaultAbbreviation(FooUnit.Bar));
Assert.AreEqual(FooUnit.Bar, unitSystem.Parse<FooUnit>("bar");

I'm not sure how useful this is, but at least this is already possibly.

Candidates for custom units

Clone this wiki locally