Skip to content

Project (source) components

mangh edited this page May 10, 2021 · 10 revisions

Component dependency diagram

Component Dependency Diagram

  • Each component has a separate solution folder: Core, Units, Parsers, RuntimeLoader.
  • RuntimeLoader and/or Parsers can be safely removed from the solution without breaking the remaining functionality.
  • External Man.UnitsOfMeasurement.Parser.dll is required for parsing unit/scale text definitions at design-time. RuntimeLoader component (if not removed) requires the parser also at run-time. The parser can be found in %LOCALAPPDATA%\Microsoft\VisualStudio\nn.n\Extensions\<VSIX_install_folder>\.

Core

  • Dimension provides dimensional aspect (sense) of units (Length, Time, Mass, Temperature etc.)
  • SymbolCollection supports multiple unit symbols (e.g.: "m", "meter", "metre" for Meter unit).
  • IQuantity<T> and ILevel<T> interfaces to be implemented by unit & scale types correspondingly.
  • Unit<T> and Scale<T> proxy types for handling unit & scale types as individual variables and their collections.

Change as of relase 2.0: Unit<T>, Scale<T> proxies (and the underlying base type Measure) have been significantly changed toward eliminating Reflection. Specific proxies are generated directly from template (_generator.tt) together with their corresponding unit/scale types (i.e. at design time). Reflection mechanism is not used at all to create or operate them. The changes allowed also to simplify IQuantity<T> and ILevel<T> interfaces.

Units

  • _definitions.txt : user definitions for unit & scale types and their relationship (input for _generator.tt).
  • _generator.tt : T4 text template for generating unit & scale types and (as of release 2.0) their proxies.
  • _unit.t4 : you can modify this file to customize generated units.
  • _scale.t4 : you can modify this file to customize generated scales.
  • _generator.txt : report from generating units & scales.
  • *.cs files dependent on _generator.tt (attached to generator tree): unit & scale types generated at each run of the generator.
  • *.cs files independent of _generator.tt (disconnected from generator tree): user .cs files for extending functionality of generated types.

New as of relase 2.0: Catalog.Populate.cs (dependent on generator) and Catalog.cs (independent of generator) are two .cs files that together establish functionality of a static Catalog class. The first one populates the Catalog with generated (proxy) types and the latter provides its functionality as a collection. The single Catalog class has replaced UnitCatalog(s) and ScaleCatalog(s) classes (heavily dependent on Reflection) in previous releases.

Parsers

  • QuantityParser<T> for parsing text input into IQuantity<T> values.
  • LevelParser<T> for parsing text input into ILevel<T> values.

Sample usage:

string input = "1 km";
var parser = new QuantityParser<double>(Meter.Family);
IQuantity<double> length;
if (!parser.TryParse(input, out length))
{
    Console.WriteLine("{0}: invalid number or unit other than any the following: \"{1}\".", 
        input, string.Join("\", \"", parser.Units.SelectMany(m => m.Symbol)));
}
else
{
    int i = 0;
    foreach (var unit in parser.Units)
    {
        string unitinfo = string.Format("{0,2}. {1}", ++i, unit);
        IQuantity<double> output = unit.From(length);
        Console.WriteLine("{0,-40}  {1} -> {2}", unitinfo, input, output);
    }
}

Sample output:

  1. [L] Meter {"m"}                       1 km -> 1000 m
  2. [L] Centimeter {"cm"}                 1 km -> 100000 cm
  3. [L] Millimeter {"mm"}                 1 km -> 1000000 mm
  4. [L] Kilometer {"km"}                  1 km -> 1 km
  5. [L] Inch {"in"}                       1 km -> 39370,0787401575 in
  6. [L] Foot {"ft"}                       1 km -> 3280,83989501312 ft
  7. [L] Yard {"yd"}                       1 km -> 1093,61329833771 yd
  8. [L] Mile {"mil"}                      1 km -> 0,621371192237334 mil

RuntimeLoader

  • To load (late) units and scales from a definition text file (or string) at run-time. Late definitions have the same syntax as compile-time definitions and may refer to compile-time units exactly the same way as if they were specified at compile time.
  • The loader requires Man.UnitsOfMeasurement.Parser.dll at runtime (apart from Core types it requires at compile-time).
  • Reflection mechanism is applied here but only to retrieve new units from the compiled late definitions and it is not used at all for operating them.

Sample definitions of late units:

// LateUnits.txt
// Note: the definitions below refer to compile-time units Foot and Meter:
unit Fathom "ftm" = Foot / 6;
unit Cable "cb" = Meter / 185.2;
unit NauticalMile "nmi" = Meter / 1852;

Sample usage:

RuntimeLoader ldr = new RuntimeLoader();
if (!ldr.LoadFromFile(Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "LateUnits.txt")))
{
    Console.WriteLine("\nInvalid definitions:");
    foreach (var e in ldr.Errors) Console.WriteLine(e);
    return;
}

string input = "1 nmi";
var parser = new QuantityParser<double>(Meter.Family);
IQuantity<double> length;
if (!parser.TryParse(input, out length))
{
    Console.WriteLine("{0}: invalid number or unit other than any the following: \"{1}\".", 
        input, string.Join("\", \"", parser.Units.SelectMany(m => m.Symbol)));
}
else
{
    int i = 0;
    foreach (var unit in parser.Units)
    {
        string unitinfo = string.Format("{0,2}. {1}", ++i, unit);
        IQuantity<double> output = unit.From(length);
        Console.WriteLine("{0,-40}  {1} -> {2}", unitinfo, input, output);
    }
}

Sample output:

 1. [L] Meter {"m"}                       1 nmi -> 1852 m
 2. [L] Centimeter {"cm"}                 1 nmi -> 185200 cm
 3. [L] Millimeter {"mm"}                 1 nmi -> 1852000 mm
 4. [L] Kilometer {"km"}                  1 nmi -> 1,852 km
 5. [L] Inch {"in"}                       1 nmi -> 72913,3858267717 in
 6. [L] Foot {"ft"}                       1 nmi -> 6076,1154855643 ft
 7. [L] Yard {"yd"}                       1 nmi -> 2025,37182852143 yd
 8. [L] Mile {"mil"}                      1 nmi -> 1,15077944802354 mil
 9. [L] Fathom {"ftm"}                    1 nmi -> 1012,68591426072 ftm
10. [L] Cable {"cb"}                      1 nmi -> 10 cb
11. [L] NauticalMile {"nmi"}              1 nmi -> 1 nmi

See Demo/RuntimeUnits and Demo/UnitsOfMeasurement.Test/CatalogTest for more samples on runtime units and parsing.