diff --git a/Build/build-functions.psm1 b/Build/build-functions.psm1
index 775db15349..9dcc3b281b 100644
--- a/Build/build-functions.psm1
+++ b/Build/build-functions.psm1
@@ -18,24 +18,9 @@ function Remove-ArtifactsDir {
}
function Update-GeneratedCode {
- # Regenerate source code since it occasionally happens that merged pull requests did not include all the regenerated code
- $genScriptDotNet = "$root/UnitsNet/Scripts/GenerateUnits.ps1"
- $genScriptWrc = "$root/UnitsNet.WindowsRuntimeComponent/Scripts/GenerateUnits.ps1"
-
- write-host -foreground blue "Generate code for .NET...`n---"
- write-host $genScriptDotNet
- & $genScriptDotNet
- if ($lastexitcode -ne 0) { exit 1 }
-
- # Regenerate WRC code even if we are not building that target.
- # The reason is that build.bat will skip WRC build since most people don't have that dependency installed.
- # AppVeyor build server would still regen and build WRC regardless, but this way we also get the changes
- # into pull requests so they are visible and master branch is kept up-to-date.
- write-host -foreground blue "Generate code for Windows Runtime Component...`n---"
- write-host $genScriptWrc
- & $genScriptWrc
+ write-host -foreground blue "Generate code...`n---"
+ dotnet run --project "$root/CodeGen"
if ($lastexitcode -ne 0) { exit 1 }
-
write-host -foreground blue "Generate code...END`n"
}
diff --git a/CodeGen/CodeGen.csproj b/CodeGen/CodeGen.csproj
new file mode 100644
index 0000000000..8fd50fc3a6
--- /dev/null
+++ b/CodeGen/CodeGen.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ netcoreapp2.1
+
+
+
+
+
+
+
+
+
+
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateQuantityTypeSourceCode.ps1 b/CodeGen/Generators/GeneratorBase.cs
similarity index 56%
rename from UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateQuantityTypeSourceCode.ps1
rename to CodeGen/Generators/GeneratorBase.cs
index 7aeae8432a..53c9a23f7f 100644
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateQuantityTypeSourceCode.ps1
+++ b/CodeGen/Generators/GeneratorBase.cs
@@ -1,7 +1,16 @@
-function GenerateQuantityTypeSourceCode($quantities)
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using CodeGen.Helpers;
+
+namespace CodeGen.Generators
{
-@"
-//------------------------------------------------------------------------------
+ internal abstract class GeneratorBase
+ {
+ protected readonly MyTextWriter Writer = new MyTextWriter();
+ public abstract string Generate();
+
+ public const string GeneratedFileHeader = @"//------------------------------------------------------------------------------
//
// This code was generated by \generate-code.bat.
//
@@ -19,24 +28,6 @@
// Licensed under MIT No Attribution, see LICENSE file at the root.
// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-// ReSharper disable once CheckNamespace
-namespace UnitsNet
-{
- ///
- /// Lists all generated quantities with the same name as the quantity struct type,
- /// such as Length, Mass, Force etc.
- /// This is useful for populating options in the UI, such as creating a generic conversion
- /// tool with inputValue, quantityName, fromUnit and toUnit selectors.
- ///
- public enum QuantityType
- {
- Undefined = 0,
-"@; foreach ($quantity in $quantities) {
-@"
- $($quantity.Name),
-"@; }@"
+";
}
}
-"@;
-}
diff --git a/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs b/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs
new file mode 100644
index 0000000000..1d8692fe51
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs
@@ -0,0 +1,1134 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+using System.Linq;
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class QuantityGenerator : GeneratorBase
+ {
+ private readonly Quantity _quantity;
+
+ private readonly bool _isDimensionless;
+ private readonly string _unitEnumName;
+ private readonly string _valueType;
+ private readonly Unit _baseUnit;
+
+ public QuantityGenerator(Quantity quantity)
+ {
+ _quantity = quantity ?? throw new ArgumentNullException(nameof(quantity));
+
+ _baseUnit = quantity.Units.FirstOrDefault(u => u.SingularName == _quantity.BaseUnit) ??
+ throw new ArgumentException($"No unit found with SingularName equal to BaseUnit [{_quantity.BaseUnit}]. This unit must be defined.",
+ nameof(quantity));
+
+ _valueType = quantity.BaseType;
+ _unitEnumName = $"{quantity.Name}Unit";
+
+ BaseDimensions baseDimensions = quantity.BaseDimensions;
+ _isDimensionless = baseDimensions == null ||
+ baseDimensions.L == 0 &&
+ baseDimensions.M == 0 &&
+ baseDimensions.T == 0 &&
+ baseDimensions.I == 0 &&
+ baseDimensions.Θ == 0 &&
+ baseDimensions.N == 0 &&
+ baseDimensions.J == 0;
+
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+using System;
+using System.Globalization;
+using System.Linq;
+using JetBrains.Annotations;
+using UnitsNet.InternalHelpers;
+using UnitsNet.Units;
+
+// ReSharper disable once CheckNamespace
+
+namespace UnitsNet
+{");
+ Writer.WLIfText(1, GetObsoleteAttributeOrNull(_quantity));
+ Writer.WL($@"
+ ///
+ ///
+ /// {_quantity.XmlDoc}
+ /// ");
+
+ Writer.WLCondition(_quantity.XmlDocRemarks.HasText(), $@"
+ ///
+ /// {_quantity.XmlDocRemarks}
+ /// ");
+
+ Writer.WL($@"
+ public partial struct {_quantity.Name} : IQuantity<{_unitEnumName}>, IEquatable<{_quantity.Name}>, IComparable, IComparable<{_quantity.Name}>, IConvertible, IFormattable
+ {{
+ ///
+ /// The numeric value this quantity was constructed with.
+ ///
+ private readonly {_quantity.BaseType} _value;
+
+ ///
+ /// The unit this quantity was constructed with.
+ ///
+ private readonly {_unitEnumName}? _unit;
+");
+ GenerateStaticConstructor();
+ GenerateInstanceConstructors();
+ GenerateStaticProperties();
+ GenerateProperties();
+ GenerateConversionProperties();
+ GenerateStaticMethods();
+ GenerateStaticFactoryMethods();
+ GenerateStaticParseMethods();
+ GenerateArithmeticOperators();
+ GenerateEqualityAndComparison();
+ GenerateConversionMethods();
+ GenerateToString();
+ GenerateIConvertibleMethods();
+
+ Writer.WL($@"
+ }}
+}}");
+ return Writer.ToString();
+ }
+
+ private void GenerateStaticConstructor()
+ {
+ var baseDimensions = _quantity.BaseDimensions;
+ Writer.WL($@"
+ static {_quantity.Name}()
+ {{");
+ Writer.WL(_isDimensionless
+ ? @"
+ BaseDimensions = BaseDimensions.Dimensionless;
+"
+ : $@"
+ BaseDimensions = new BaseDimensions({baseDimensions.L}, {baseDimensions.M}, {baseDimensions.T}, {baseDimensions.I}, {baseDimensions.Θ}, {baseDimensions.N}, {baseDimensions.J});
+");
+
+ Writer.WL($@"
+ Info = new QuantityInfo<{_unitEnumName}>(QuantityType.{_quantity.Name},
+ new UnitInfo<{_unitEnumName}>[] {{");
+
+ foreach (var unit in _quantity.Units)
+ {
+ var baseUnits = unit.BaseUnits;
+ if (baseUnits == null)
+ {
+ Writer.WL($@"
+ new UnitInfo<{_unitEnumName}>({_unitEnumName}.{unit.SingularName}, BaseUnits.Undefined),");
+ }
+ else
+ {
+ var baseUnitsCtorArgs = string.Join(", ",
+ new[]
+ {
+ baseUnits.L != null ? $"length: LengthUnit.{baseUnits.L}" : null,
+ baseUnits.M != null ? $"mass: MassUnit.{baseUnits.M}" : null,
+ baseUnits.T != null ? $"time: DurationUnit.{baseUnits.T}" : null,
+ baseUnits.I != null ? $"current: ElectricCurrentUnit.{baseUnits.I}" : null,
+ baseUnits.Θ != null ? $"temperature: TemperatureUnit.{baseUnits.Θ}" : null,
+ baseUnits.N != null ? $"amount: AmountOfSubstanceUnit.{baseUnits.N}" : null,
+ baseUnits.J != null ? $"luminousIntensity: LuminousIntensityUnit.{baseUnits.J}" : null
+ }.Where(str => str != null));
+
+ Writer.WL($@"
+ new UnitInfo<{_unitEnumName}>({_unitEnumName}.{unit.SingularName}, new BaseUnits({baseUnitsCtorArgs})),");
+ }
+ }
+
+ Writer.WL(@"
+ },
+ BaseUnit, Zero, BaseDimensions);
+ }
+");
+ }
+
+ private void GenerateInstanceConstructors()
+ {
+ Writer.WL($@"
+ ///
+ /// Creates the quantity with the given numeric value and unit.
+ ///
+ /// The numeric value to contruct this quantity with.
+ /// The unit representation to contruct this quantity with.
+ /// If value is NaN or Infinity.
+ public {_quantity.Name}({_quantity.BaseType} numericValue, {_unitEnumName} unit)
+ {{
+ if(unit == {_unitEnumName}.Undefined)
+ throw new ArgumentException(""The quantity can not be created with an undefined unit."", nameof(unit));
+");
+
+ Writer.WL(_quantity.BaseType == "double"
+ ? @"
+ _value = Guard.EnsureValidNumber(numericValue, nameof(numericValue));"
+ : @"
+ _value = numericValue;");
+ Writer.WL($@"
+ _unit = unit;
+ }}
+
+ ///
+ /// Creates an instance of the quantity with the given numeric value in units compatible with the given .
+ /// If multiple compatible units were found, the first match is used.
+ ///
+ /// The numeric value to contruct this quantity with.
+ /// The unit system to create the quantity with.
+ /// The given is null.
+ /// No unit was found for the given .
+ public {_quantity.Name}({_valueType} numericValue, UnitSystem unitSystem)
+ {{
+ if(unitSystem == null) throw new ArgumentNullException(nameof(unitSystem));
+
+ var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
+ var firstUnitInfo = unitInfos.FirstOrDefault();
+");
+
+ Writer.WL(_quantity.BaseType == "double"
+ ? @"
+ _value = Guard.EnsureValidNumber(numericValue, nameof(numericValue));"
+ : @"
+ _value = numericValue;");
+ Writer.WL(@"
+ _unit = firstUnitInfo?.Value ?? throw new ArgumentException(""No units were found for the given UnitSystem."", nameof(unitSystem));
+ }
+");
+ }
+
+ private void GenerateStaticProperties()
+ {
+ Writer.WL($@"
+ #region Static Properties
+
+ ///
+ public static QuantityInfo<{_unitEnumName}> Info {{ get; }}
+
+ ///
+ /// The of this quantity.
+ ///
+ public static BaseDimensions BaseDimensions {{ get; }}
+
+ ///
+ /// The base unit of {_quantity.Name}, which is {_quantity.BaseUnit}. All conversions go via this value.
+ ///
+ public static {_unitEnumName} BaseUnit {{ get; }} = {_unitEnumName}.{_quantity.BaseUnit};
+
+ ///
+ /// Represents the largest possible value of {_quantity.Name}
+ ///
+ public static {_quantity.Name} MaxValue {{ get; }} = new {_quantity.Name}({_valueType}.MaxValue, BaseUnit);
+
+ ///
+ /// Represents the smallest possible value of {_quantity.Name}
+ ///
+ public static {_quantity.Name} MinValue {{ get; }} = new {_quantity.Name}({_valueType}.MinValue, BaseUnit);
+
+ ///
+ /// The of this quantity.
+ ///
+ public static QuantityType QuantityType {{ get; }} = QuantityType.{_quantity.Name};
+
+ ///
+ /// All units of measurement for the {_quantity.Name} quantity.
+ ///
+ public static {_unitEnumName}[] Units {{ get; }} = Enum.GetValues(typeof({_unitEnumName})).Cast<{_unitEnumName}>().Except(new {_unitEnumName}[]{{ {_unitEnumName}.Undefined }}).ToArray();
+
+ ///
+ /// Gets an instance of this quantity with a value of 0 in the base unit {_quantity.BaseUnit}.
+ ///
+ public static {_quantity.Name} Zero {{ get; }} = new {_quantity.Name}(0, BaseUnit);
+
+ #endregion
+");
+ }
+
+ private void GenerateProperties()
+ {
+ Writer.WL($@"
+ #region Properties
+
+ ///
+ /// The numeric value this quantity was constructed with.
+ ///
+ public {_valueType} Value => _value;
+");
+
+ // Need to provide explicit interface implementation for decimal quantities like Information
+ if (_quantity.BaseType != "double")
+ Writer.WL(@"
+ double IQuantity.Value => (double) _value;
+");
+
+ Writer.WL($@"
+ Enum IQuantity.Unit => Unit;
+
+ ///
+ public {_unitEnumName} Unit => _unit.GetValueOrDefault(BaseUnit);
+
+ ///
+ public QuantityInfo<{_unitEnumName}> QuantityInfo => Info;
+
+ ///
+ QuantityInfo IQuantity.QuantityInfo => Info;
+
+ ///
+ /// The of this quantity.
+ ///
+ public QuantityType Type => {_quantity.Name}.QuantityType;
+
+ ///
+ /// The of this quantity.
+ ///
+ public BaseDimensions Dimensions => {_quantity.Name}.BaseDimensions;
+
+ #endregion
+");
+ }
+
+ private void GenerateConversionProperties()
+ {
+ Writer.WL(@"
+ #region Conversion Properties
+");
+ foreach (var unit in _quantity.Units)
+ {
+ Writer.WL($@"
+ ///
+ /// Get {_quantity.Name} in {unit.PluralName}.
+ /// ");
+ Writer.WLIfText(2, GetObsoleteAttributeOrNull(unit));
+ Writer.WL($@"
+ public double {unit.PluralName} => As({_unitEnumName}.{unit.SingularName});
+");
+ }
+
+ Writer.WL(@"
+
+ #endregion
+");
+ }
+
+ private void GenerateStaticMethods()
+ {
+ Writer.WL($@"
+
+ #region Static Methods
+
+ ///
+ /// Get unit abbreviation string.
+ ///
+ /// Unit to get abbreviation for.
+ /// Unit abbreviation string.
+ public static string GetAbbreviation({_unitEnumName} unit)
+ {{
+ return GetAbbreviation(unit, null);
+ }}
+
+ ///
+ /// Get unit abbreviation string.
+ ///
+ /// Unit to get abbreviation for.
+ /// Unit abbreviation string.
+ /// Format to use for localization. Defaults to if null.
+ public static string GetAbbreviation({_unitEnumName} unit, [CanBeNull] IFormatProvider provider)
+ {{
+ return UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit, provider);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateStaticFactoryMethods()
+ {
+ Writer.WL(@"
+ #region Static Factory Methods
+");
+ foreach (var unit in _quantity.Units)
+ {
+ var valueParamName = unit.PluralName.ToLowerInvariant();
+ Writer.WL($@"
+ ///
+ /// Get {_quantity.Name} from {unit.PluralName}.
+ ///
+ /// If value is NaN or Infinity.");
+ Writer.WLIfText(2, GetObsoleteAttributeOrNull(unit));
+ Writer.WL($@"
+ public static {_quantity.Name} From{unit.PluralName}(QuantityValue {valueParamName})
+ {{
+ {_valueType} value = ({_valueType}) {valueParamName};
+ return new {_quantity.Name}(value, {_unitEnumName}.{unit.SingularName});
+ }}");
+ }
+
+ Writer.WL();
+ Writer.WL($@"
+ ///
+ /// Dynamically convert from value and unit enum to .
+ ///
+ /// Value to convert from.
+ /// Unit to convert from.
+ /// {_quantity.Name} unit value.
+ public static {_quantity.Name} From(QuantityValue value, {_unitEnumName} fromUnit)
+ {{
+ return new {_quantity.Name}(({_valueType})value, fromUnit);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateStaticParseMethods()
+ {
+ Writer.WL($@"
+ #region Static Parse Methods
+
+ ///
+ /// Parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ ///
+ /// Expected string to have one or two pairs of quantity and unit in the format
+ /// ""<quantity> <unit>"". Eg. ""5.5 m"" or ""1ft 2in""
+ ///
+ ///
+ /// More than one unit is represented by the specified unit abbreviation.
+ /// Example: Volume.Parse(""1 cup"") will throw, because it can refer to any of
+ /// , and .
+ ///
+ ///
+ /// If anything else goes wrong, typically due to a bug or unhandled case.
+ /// We wrap exceptions in to allow you to distinguish
+ /// Units.NET exceptions from other exceptions.
+ ///
+ public static {_quantity.Name} Parse(string str)
+ {{
+ return Parse(str, null);
+ }}
+
+ ///
+ /// Parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ ///
+ /// Expected string to have one or two pairs of quantity and unit in the format
+ /// ""<quantity> <unit>"". Eg. ""5.5 m"" or ""1ft 2in""
+ ///
+ ///
+ /// More than one unit is represented by the specified unit abbreviation.
+ /// Example: Volume.Parse(""1 cup"") will throw, because it can refer to any of
+ /// , and .
+ ///
+ ///
+ /// If anything else goes wrong, typically due to a bug or unhandled case.
+ /// We wrap exceptions in to allow you to distinguish
+ /// Units.NET exceptions from other exceptions.
+ ///
+ /// Format to use when parsing number and unit. Defaults to if null.
+ public static {_quantity.Name} Parse(string str, [CanBeNull] IFormatProvider provider)
+ {{
+ return QuantityParser.Default.Parse<{_quantity.Name}, {_unitEnumName}>(
+ str,
+ provider,
+ From);
+ }}
+
+ ///
+ /// Try to parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ /// Resulting unit quantity if successful.
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ public static bool TryParse([CanBeNull] string str, out {_quantity.Name} result)
+ {{
+ return TryParse(str, null, out result);
+ }}
+
+ ///
+ /// Try to parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ /// Resulting unit quantity if successful.
+ /// True if successful, otherwise false.
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ /// Format to use when parsing number and unit. Defaults to if null.
+ public static bool TryParse([CanBeNull] string str, [CanBeNull] IFormatProvider provider, out {_quantity.Name} result)
+ {{
+ return QuantityParser.Default.TryParse<{_quantity.Name}, {_unitEnumName}>(
+ str,
+ provider,
+ From,
+ out result);
+ }}
+
+ ///
+ /// Parse a unit string.
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.ParseUnit(""m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ /// Error parsing string.
+ public static {_unitEnumName} ParseUnit(string str)
+ {{
+ return ParseUnit(str, null);
+ }}
+
+ ///
+ /// Parse a unit string.
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.ParseUnit(""m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ /// Error parsing string.
+ /// Format to use when parsing number and unit. Defaults to if null.
+ public static {_unitEnumName} ParseUnit(string str, IFormatProvider provider = null)
+ {{
+ return UnitParser.Default.Parse<{_unitEnumName}>(str, provider);
+ }}
+
+ ///
+ public static bool TryParseUnit(string str, out {_unitEnumName} unit)
+ {{
+ return TryParseUnit(str, null, out unit);
+ }}
+
+ ///
+ /// Parse a unit string.
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ /// The parsed unit if successful.
+ /// True if successful, otherwise false.
+ ///
+ /// Length.TryParseUnit(""m"", new CultureInfo(""en-US""));
+ ///
+ /// Format to use when parsing number and unit. Defaults to if null.
+ public static bool TryParseUnit(string str, IFormatProvider provider, out {_unitEnumName} unit)
+ {{
+ return UnitParser.Default.TryParse<{_unitEnumName}>(str, provider, out unit);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateArithmeticOperators()
+ {
+ if (!_quantity.GenerateArithmetic)
+ return;
+
+ // Logarithmic units required different arithmetic
+ if (_quantity.Logarithmic)
+ {
+ GenerateLogarithmicArithmeticOperators();
+ return;
+ }
+
+ Writer.WL($@"
+ #region Arithmetic Operators
+
+ /// Negate the value.
+ public static {_quantity.Name} operator -({_quantity.Name} right)
+ {{
+ return new {_quantity.Name}(-right.Value, right.Unit);
+ }}
+
+ /// Get from adding two .
+ public static {_quantity.Name} operator +({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return new {_quantity.Name}(left.Value + right.GetValueAs(left.Unit), left.Unit);
+ }}
+
+ /// Get from subtracting two .
+ public static {_quantity.Name} operator -({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return new {_quantity.Name}(left.Value - right.GetValueAs(left.Unit), left.Unit);
+ }}
+
+ /// Get from multiplying value and .
+ public static {_quantity.Name} operator *({_valueType} left, {_quantity.Name} right)
+ {{
+ return new {_quantity.Name}(left * right.Value, right.Unit);
+ }}
+
+ /// Get from multiplying value and .
+ public static {_quantity.Name} operator *({_quantity.Name} left, {_valueType} right)
+ {{
+ return new {_quantity.Name}(left.Value * right, left.Unit);
+ }}
+
+ /// Get from dividing by value.
+ public static {_quantity.Name} operator /({_quantity.Name} left, {_valueType} right)
+ {{
+ return new {_quantity.Name}(left.Value / right, left.Unit);
+ }}
+
+ /// Get ratio value from dividing by .
+ public static double operator /({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return left.{_baseUnit.PluralName} / right.{_baseUnit.PluralName};
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateLogarithmicArithmeticOperators()
+ {
+ var scalingFactor = _quantity.LogarithmicScalingFactor;
+ // Most logarithmic operators need a simple scaling factor of 10. However, certain units such as voltage ratio need to use 20 instead.
+ var x = (10 * scalingFactor).ToString();
+ Writer.WL($@"
+ #region Logarithmic Arithmetic Operators
+
+ /// Negate the value.
+ public static {_quantity.Name} operator -({_quantity.Name} right)
+ {{
+ return new {_quantity.Name}(-right.Value, right.Unit);
+ }}
+
+ /// Get from logarithmic addition of two .
+ public static {_quantity.Name} operator +({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ // Logarithmic addition
+ // Formula: {x}*log10(10^(x/{x}) + 10^(y/{x}))
+ return new {_quantity.Name}({x}*Math.Log10(Math.Pow(10, left.Value/{x}) + Math.Pow(10, right.GetValueAs(left.Unit)/{x})), left.Unit);
+ }}
+
+ /// Get from logarithmic subtraction of two .
+ public static {_quantity.Name} operator -({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ // Logarithmic subtraction
+ // Formula: {x}*log10(10^(x/{x}) - 10^(y/{x}))
+ return new {_quantity.Name}({x}*Math.Log10(Math.Pow(10, left.Value/{x}) - Math.Pow(10, right.GetValueAs(left.Unit)/{x})), left.Unit);
+ }}
+
+ /// Get from logarithmic multiplication of value and .
+ public static {_quantity.Name} operator *({_valueType} left, {_quantity.Name} right)
+ {{
+ // Logarithmic multiplication = addition
+ return new {_quantity.Name}(left + right.Value, right.Unit);
+ }}
+
+ /// Get from logarithmic multiplication of value and .
+ public static {_quantity.Name} operator *({_quantity.Name} left, double right)
+ {{
+ // Logarithmic multiplication = addition
+ return new {_quantity.Name}(left.Value + ({_valueType})right, left.Unit);
+ }}
+
+ /// Get from logarithmic division of by value.
+ public static {_quantity.Name} operator /({_quantity.Name} left, double right)
+ {{
+ // Logarithmic division = subtraction
+ return new {_quantity.Name}(left.Value - ({_valueType})right, left.Unit);
+ }}
+
+ /// Get ratio value from logarithmic division of by .
+ public static double operator /({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ // Logarithmic division = subtraction
+ return Convert.ToDouble(left.Value - right.GetValueAs(left.Unit));
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateEqualityAndComparison()
+ {
+ Writer.WL($@"
+ #region Equality / IComparable
+
+ /// Returns true if less or equal to.
+ public static bool operator <=({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return left.Value <= right.GetValueAs(left.Unit);
+ }}
+
+ /// Returns true if greater than or equal to.
+ public static bool operator >=({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return left.Value >= right.GetValueAs(left.Unit);
+ }}
+
+ /// Returns true if less than.
+ public static bool operator <({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return left.Value < right.GetValueAs(left.Unit);
+ }}
+
+ /// Returns true if greater than.
+ public static bool operator >({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return left.Value > right.GetValueAs(left.Unit);
+ }}
+
+ /// Returns true if exactly equal.
+ /// Consider using for safely comparing floating point values.
+ public static bool operator ==({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return left.Equals(right);
+ }}
+
+ /// Returns true if not exactly equal.
+ /// Consider using for safely comparing floating point values.
+ public static bool operator !=({_quantity.Name} left, {_quantity.Name} right)
+ {{
+ return !(left == right);
+ }}
+
+ ///
+ public int CompareTo(object obj)
+ {{
+ if(obj is null) throw new ArgumentNullException(nameof(obj));
+ if(!(obj is {_quantity.Name} obj{_quantity.Name})) throw new ArgumentException(""Expected type {_quantity.Name}."", nameof(obj));
+
+ return CompareTo(obj{_quantity.Name});
+ }}
+
+ ///
+ public int CompareTo({_quantity.Name} other)
+ {{
+ return _value.CompareTo(other.GetValueAs(this.Unit));
+ }}
+
+ ///
+ /// Consider using for safely comparing floating point values.
+ public override bool Equals(object obj)
+ {{
+ if(obj is null || !(obj is {_quantity.Name} obj{_quantity.Name}))
+ return false;
+
+ return Equals(obj{_quantity.Name});
+ }}
+
+ ///
+ /// Consider using for safely comparing floating point values.
+ public bool Equals({_quantity.Name} other)
+ {{
+ return _value.Equals(other.GetValueAs(this.Unit));
+ }}
+
+ ///
+ ///
+ /// Compare equality to another {_quantity.Name} within the given absolute or relative tolerance.
+ ///
+ ///
+ /// Relative tolerance is defined as the maximum allowable absolute difference between this quantity's value and
+ /// as a percentage of this quantity's value. will be converted into
+ /// this quantity's unit for comparison. A relative tolerance of 0.01 means the absolute difference must be within +/- 1% of
+ /// this quantity's value to be considered equal.
+ ///
+ /// In this example, the two quantities will be equal if the value of b is within +/- 1% of a (0.02m or 2cm).
+ ///
+ /// var a = Length.FromMeters(2.0);
+ /// var b = Length.FromInches(50.0);
+ /// a.Equals(b, 0.01, ComparisonType.Relative);
+ ///
+ ///
+ ///
+ ///
+ /// Absolute tolerance is defined as the maximum allowable absolute difference between this quantity's value and
+ /// as a fixed number in this quantity's unit. will be converted into
+ /// this quantity's unit for comparison.
+ ///
+ /// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
+ ///
+ /// var a = Length.FromMeters(2.0);
+ /// var b = Length.FromInches(50.0);
+ /// a.Equals(b, 0.01, ComparisonType.Absolute);
+ ///
+ ///
+ ///
+ ///
+ /// Note that it is advised against specifying zero difference, due to the nature
+ /// of floating point operations and using System.Double internally.
+ ///
+ ///
+ /// The other quantity to compare to.
+ /// The absolute or relative tolerance value. Must be greater than or equal to 0.
+ /// The comparison type: either relative or absolute.
+ /// True if the absolute difference between the two values is not greater than the specified relative or absolute tolerance.
+ public bool Equals({_quantity.Name} other, double tolerance, ComparisonType comparisonType)
+ {{
+ if(tolerance < 0)
+ throw new ArgumentOutOfRangeException(""tolerance"", ""Tolerance must be greater than or equal to 0."");
+
+ double thisValue = (double)this.Value;
+ double otherValueInThisUnits = other.As(this.Unit);
+
+ return UnitsNet.Comparison.Equals(thisValue, otherValueInThisUnits, tolerance, comparisonType);
+ }}
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// A hash code for the current {_quantity.Name}.
+ public override int GetHashCode()
+ {{
+ return new {{ QuantityType, Value, Unit }}.GetHashCode();
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateConversionMethods()
+ {
+ Writer.WL($@"
+ #region Conversion Methods
+
+ ///
+ /// Convert to the unit representation .
+ ///
+ /// Value converted to the specified unit.
+ public double As({_unitEnumName} unit)
+ {{
+ if(Unit == unit)
+ return Convert.ToDouble(Value);
+
+ var converted = GetValueAs(unit);
+ return Convert.ToDouble(converted);
+ }}
+
+ ///
+ public double As(UnitSystem unitSystem)
+ {{
+ if(unitSystem == null)
+ throw new ArgumentNullException(nameof(unitSystem));
+
+ var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
+
+ var firstUnitInfo = unitInfos.FirstOrDefault();
+ if(firstUnitInfo == null)
+ throw new ArgumentException(""No units were found for the given UnitSystem."", nameof(unitSystem));
+
+ return As(firstUnitInfo.Value);
+ }}
+
+ ///
+ double IQuantity.As(Enum unit)
+ {{
+ if(!(unit is {_unitEnumName} unitAs{_unitEnumName}))
+ throw new ArgumentException($""The given unit is of type {{unit.GetType()}}. Only {{typeof({_unitEnumName})}} is supported."", nameof(unit));
+
+ return As(unitAs{_unitEnumName});
+ }}
+
+ ///
+ /// Converts this {_quantity.Name} to another {_quantity.Name} with the unit representation .
+ ///
+ /// A {_quantity.Name} with the specified unit.
+ public {_quantity.Name} ToUnit({_unitEnumName} unit)
+ {{
+ var convertedValue = GetValueAs(unit);
+ return new {_quantity.Name}(convertedValue, unit);
+ }}
+
+ ///
+ IQuantity IQuantity.ToUnit(Enum unit)
+ {{
+ if(!(unit is {_unitEnumName} unitAs{_unitEnumName}))
+ throw new ArgumentException($""The given unit is of type {{unit.GetType()}}. Only {{typeof({_unitEnumName})}} is supported."", nameof(unit));
+
+ return ToUnit(unitAs{_unitEnumName});
+ }}
+
+ ///
+ public {_quantity.Name} ToUnit(UnitSystem unitSystem)
+ {{
+ if(unitSystem == null)
+ throw new ArgumentNullException(nameof(unitSystem));
+
+ var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
+
+ var firstUnitInfo = unitInfos.FirstOrDefault();
+ if(firstUnitInfo == null)
+ throw new ArgumentException(""No units were found for the given UnitSystem."", nameof(unitSystem));
+
+ return ToUnit(firstUnitInfo.Value);
+ }}
+
+ ///
+ IQuantity IQuantity.ToUnit(UnitSystem unitSystem) => ToUnit(unitSystem);
+
+ ///
+ IQuantity<{_unitEnumName}> IQuantity<{_unitEnumName}>.ToUnit({_unitEnumName} unit) => ToUnit(unit);
+
+ ///
+ IQuantity<{_unitEnumName}> IQuantity<{_unitEnumName}>.ToUnit(UnitSystem unitSystem) => ToUnit(unitSystem);
+
+ ///
+ /// Converts the current value + unit to the base unit.
+ /// This is typically the first step in converting from one unit to another.
+ ///
+ /// The value in the base unit representation.
+ private {_valueType} GetValueInBaseUnit()
+ {{
+ switch(Unit)
+ {{");
+ foreach (var unit in _quantity.Units)
+ {
+ var func = unit.FromUnitToBaseFunc.Replace("x", "_value");
+ Writer.WL($@"
+ case {_unitEnumName}.{unit.SingularName}: return {func};");
+ }
+
+ Writer.WL($@"
+ default:
+ throw new NotImplementedException($""Can not convert {{Unit}} to base units."");
+ }}
+ }}
+
+ private {_valueType} GetValueAs({_unitEnumName} unit)
+ {{
+ if(Unit == unit)
+ return _value;
+
+ var baseUnitValue = GetValueInBaseUnit();
+
+ switch(unit)
+ {{");
+ foreach (var unit in _quantity.Units)
+ {
+ var func = unit.FromBaseToUnitFunc.Replace("x", "baseUnitValue");
+ Writer.WL($@"
+ case {_unitEnumName}.{unit.SingularName}: return {func};");
+ }
+
+ Writer.WL(@"
+ default:
+ throw new NotImplementedException($""Can not convert {Unit} to {unit}."");
+ }
+ }
+
+ #endregion
+");
+ }
+
+ private void GenerateToString()
+ {
+ Writer.WL($@"
+ #region ToString Methods
+
+ ///
+ /// Gets the default string representation of value and unit.
+ ///
+ /// String representation.
+ public override string ToString()
+ {{
+ return ToString(""g"");
+ }}
+
+ ///
+ /// Gets the default string representation of value and unit using the given format provider.
+ ///
+ /// String representation.
+ /// Format to use for localization and number formatting. Defaults to if null.
+ public string ToString([CanBeNull] IFormatProvider provider)
+ {{
+ return ToString(""g"", provider);
+ }}
+
+ ///
+ /// Get string representation of value and unit.
+ ///
+ /// The number of significant digits after the radix point.
+ /// String representation.
+ /// Format to use for localization and number formatting. Defaults to if null.
+ [Obsolete(@""This method is deprecated and will be removed at a future release. Please use ToString(""""s2"""") or ToString(""""s2"""", provider) where 2 is an example of the number passed to significantDigitsAfterRadix."")]
+ public string ToString([CanBeNull] IFormatProvider provider, int significantDigitsAfterRadix)
+ {{
+ var value = Convert.ToDouble(Value);
+ var format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix);
+ return ToString(provider, format);
+ }}
+
+ ///
+ /// Get string representation of value and unit.
+ ///
+ /// String format to use. Default: ""{{0:0.##}} {{1}} for value and unit abbreviation respectively.""
+ /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1.
+ /// String representation.
+ /// Format to use for localization and number formatting. Defaults to if null.
+ [Obsolete(""This method is deprecated and will be removed at a future release. Please use string.Format()."")]
+ public string ToString([CanBeNull] IFormatProvider provider, [NotNull] string format, [NotNull] params object[] args)
+ {{
+ if (format == null) throw new ArgumentNullException(nameof(format));
+ if (args == null) throw new ArgumentNullException(nameof(args));
+
+ provider = provider ?? CultureInfo.CurrentUICulture;
+
+ var value = Convert.ToDouble(Value);
+ var formatArgs = UnitFormatter.GetFormatArgs(Unit, value, provider, args);
+ return string.Format(provider, format, formatArgs);
+ }}
+
+ ///
+ ///
+ /// Gets the string representation of this instance in the specified format string using .
+ ///
+ /// The format string.
+ /// The string representation.
+ public string ToString(string format)
+ {{
+ return ToString(format, CultureInfo.CurrentUICulture);
+ }}
+
+ ///
+ ///
+ /// Gets the string representation of this instance in the specified format string using the specified format provider, or if null.
+ ///
+ /// The format string.
+ /// Format to use for localization and number formatting. Defaults to if null.
+ /// The string representation.
+ public string ToString(string format, IFormatProvider formatProvider)
+ {{
+ return QuantityFormatter.Format<{_unitEnumName}>(this, format, formatProvider);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateIConvertibleMethods()
+ {
+ Writer.WL($@"
+ #region IConvertible Methods
+
+ TypeCode IConvertible.GetTypeCode()
+ {{
+ return TypeCode.Object;
+ }}
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {{
+ throw new InvalidCastException($""Converting {{typeof({_quantity.Name})}} to bool is not supported."");
+ }}
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {{
+ return Convert.ToByte(_value);
+ }}
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {{
+ throw new InvalidCastException($""Converting {{typeof({_quantity.Name})}} to char is not supported."");
+ }}
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {{
+ throw new InvalidCastException($""Converting {{typeof({_quantity.Name})}} to DateTime is not supported."");
+ }}
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {{
+ return Convert.ToDecimal(_value);
+ }}
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {{
+ return Convert.ToDouble(_value);
+ }}
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {{
+ return Convert.ToInt16(_value);
+ }}
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {{
+ return Convert.ToInt32(_value);
+ }}
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {{
+ return Convert.ToInt64(_value);
+ }}
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {{
+ return Convert.ToSByte(_value);
+ }}
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {{
+ return Convert.ToSingle(_value);
+ }}
+
+ string IConvertible.ToString(IFormatProvider provider)
+ {{
+ return ToString(""g"", provider);
+ }}
+
+ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+ {{
+ if(conversionType == typeof({_quantity.Name}))
+ return this;
+ else if(conversionType == typeof({_unitEnumName}))
+ return Unit;
+ else if(conversionType == typeof(QuantityType))
+ return {_quantity.Name}.QuantityType;
+ else if(conversionType == typeof(BaseDimensions))
+ return {_quantity.Name}.BaseDimensions;
+ else
+ throw new InvalidCastException($""Converting {{typeof({_quantity.Name})}} to {{conversionType}} is not supported."");
+ }}
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {{
+ return Convert.ToUInt16(_value);
+ }}
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {{
+ return Convert.ToUInt32(_value);
+ }}
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {{
+ return Convert.ToUInt64(_value);
+ }}
+
+ #endregion");
+ }
+
+ ///
+ internal static string GetObsoleteAttributeOrNull(Quantity quantity) => GetObsoleteAttributeOrNull(quantity.ObsoleteText);
+
+ ///
+ internal static string GetObsoleteAttributeOrNull(Unit unit) => GetObsoleteAttributeOrNull(unit.ObsoleteText);
+
+ ///
+ /// Returns the Obsolete attribute if ObsoleteText has been defined on the JSON input - otherwise returns empty string
+ /// It is up to the consumer to wrap any padding/new lines in order to keep to correct indentation formats
+ ///
+ private static string GetObsoleteAttributeOrNull(string obsoleteText) => string.IsNullOrWhiteSpace(obsoleteText)
+ ? null
+ : $"[System.Obsolete({obsoleteText})]";
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGen/QuantityTypeGenerator.cs b/CodeGen/Generators/UnitsNetGen/QuantityTypeGenerator.cs
new file mode 100644
index 0000000000..b105c5cbc6
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/QuantityTypeGenerator.cs
@@ -0,0 +1,43 @@
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class QuantityTypeGenerator : GeneratorBase
+ {
+ private readonly Quantity[] _quantities;
+
+ public QuantityTypeGenerator(Quantity[] quantities)
+ {
+ _quantities = quantities;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+// ReSharper disable once CheckNamespace
+namespace UnitsNet
+{
+ ///
+ /// Lists all generated quantities with the same name as the quantity struct type,
+ /// such as Length, Mass, Force etc.
+ /// This is useful for populating options in the UI, such as creating a generic conversion
+ /// tool with inputValue, quantityName, fromUnit and toUnit selectors.
+ ///
+ public enum QuantityType
+ {
+// Missing XML comment for public type or member
+#pragma warning disable CS1591
+ Undefined = 0,");
+ foreach (var quantity in _quantities)
+ Writer.WL($@"
+ {quantity.Name},");
+ Writer.WL(@"
+// Missing XML comment for public type or member
+#pragma warning restore CS1591
+ }
+}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs b/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs
new file mode 100644
index 0000000000..25d9143e49
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs
@@ -0,0 +1,124 @@
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class StaticQuantityGenerator : GeneratorBase
+ {
+ private readonly Quantity[] _quantities;
+
+ public StaticQuantityGenerator(Quantity[] quantities)
+ {
+ _quantities = quantities;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+using System;
+using System.Globalization;
+using JetBrains.Annotations;
+using UnitsNet.InternalHelpers;
+using UnitsNet.Units;
+
+namespace UnitsNet
+{
+ ///
+ /// Dynamically parse or construct quantities when types are only known at runtime.
+ ///
+ public static partial class Quantity
+ {
+ ///
+ /// Dynamically constructs a quantity of the given with the value in the quantity's base units.
+ ///
+ /// The of the quantity to create.
+ /// The value to construct the quantity with.
+ /// The created quantity.
+ public static IQuantity FromQuantityType(QuantityType quantityType, QuantityValue value)
+ {
+ switch(quantityType)
+ {");
+ foreach (var quantity in _quantities)
+ {
+ var quantityName = quantity.Name;
+ Writer.WL($@"
+ case QuantityType.{quantityName}:
+ return {quantityName}.From(value, {quantityName}.BaseUnit);");
+ }
+
+ Writer.WL(@"
+ default:
+ throw new ArgumentException($""{quantityType} is not a supported quantity type."");
+ }
+ }
+
+ ///
+ /// Try to dynamically construct a quantity.
+ ///
+ /// Numeric value.
+ /// Unit enum value.
+ /// The resulting quantity if successful, otherwise default.
+ /// True if successful with assigned the value, otherwise false.
+ public static bool TryFrom(QuantityValue value, Enum unit, out IQuantity quantity)
+ {
+ switch (unit)
+ {");
+ foreach (var quantity in _quantities)
+ {
+ var quantityName = quantity.Name;
+ var unitTypeName = $"{quantityName}Unit";
+ var unitValue = unitTypeName.ToCamelCase();
+ Writer.WL($@"
+ case {unitTypeName} {unitValue}:
+ quantity = {quantityName}.From(value, {unitValue});
+ return true;");
+ }
+
+ Writer.WL(@"
+ default:
+ {
+ quantity = default(IQuantity);
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Try to dynamically parse a quantity string representation.
+ ///
+ /// The format provider to use for lookup. Defaults to if null.
+ /// Type of quantity, such as .
+ /// Quantity string representation, such as ""1.5 kg"". Must be compatible with given quantity type.
+ /// The resulting quantity if successful, otherwise default.
+ /// The parsed quantity.
+ public static bool TryParse([CanBeNull] IFormatProvider formatProvider, Type quantityType, string quantityString, out IQuantity quantity)
+ {
+ quantity = default(IQuantity);
+
+ if (!typeof(IQuantity).Wrap().IsAssignableFrom(quantityType))
+ return false;
+
+ var parser = QuantityParser.Default;
+
+ switch(quantityType)
+ {");
+ foreach (var quantity in _quantities)
+ {
+ var quantityName = quantity.Name;
+ Writer.WL($@"
+ case Type _ when quantityType == typeof({quantityName}):
+ return parser.TryParse<{quantityName}, {quantityName}Unit>(quantityString, formatProvider, {quantityName}.From, out quantity);");
+ }
+
+ Writer.WL(@"
+ default:
+ return false;
+ }
+ }
+ }
+}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGen/UnitAbbreviationsCacheGenerator.cs b/CodeGen/Generators/UnitsNetGen/UnitAbbreviationsCacheGenerator.cs
new file mode 100644
index 0000000000..26189a0172
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/UnitAbbreviationsCacheGenerator.cs
@@ -0,0 +1,58 @@
+using System.Linq;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class UnitAbbreviationsCacheGenerator : GeneratorBase
+ {
+ private readonly Quantity[] _quantities;
+
+ public UnitAbbreviationsCacheGenerator(Quantity[] quantities)
+ {
+ _quantities = quantities;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+using System;
+using UnitsNet.Units;
+
+// ReSharper disable RedundantCommaInArrayInitializer
+// ReSharper disable once CheckNamespace
+namespace UnitsNet
+{
+ public partial class UnitAbbreviationsCache
+ {
+ private static readonly (string CultureName, Type UnitType, int UnitValue, string[] UnitAbbreviations)[] GeneratedLocalizations
+ = new []
+ {");
+ foreach (var quantity in _quantities)
+ {
+ var unitEnumName = $"{quantity.Name}Unit";
+
+ foreach (var unit in quantity.Units)
+ {
+ foreach (var localization in unit.Localization)
+ {
+ var cultureName = localization.Culture;
+
+ // All units must have a unit abbreviation, so fallback to "" for units with no abbreviations defined in JSON
+ var abbreviationParams = localization.Abbreviations.Any()
+ ? string.Join(", ", localization.Abbreviations.Select(abbr => $"\"{abbr}\""))
+ : "\"\"";
+ Writer.WL($@"
+ (""{cultureName}"", typeof({unitEnumName}), (int){unitEnumName}.{unit.SingularName}, new string[]{{{abbreviationParams}}}),");
+ }
+ }
+ }
+
+ Writer.WL(@"
+ };
+ }
+}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGen/UnitTestBaseClassGenerator.cs b/CodeGen/Generators/UnitsNetGen/UnitTestBaseClassGenerator.cs
new file mode 100644
index 0000000000..41f6edb63f
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/UnitTestBaseClassGenerator.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Linq;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class UnitTestBaseClassGenerator : GeneratorBase
+ {
+ private readonly Quantity _quantity;
+ private readonly Unit _baseUnit;
+ private readonly string _unitEnumName;
+
+ public UnitTestBaseClassGenerator(Quantity quantity)
+ {
+ _quantity = quantity;
+ _baseUnit = quantity.Units.FirstOrDefault(u => u.SingularName == _quantity.BaseUnit) ??
+ throw new ArgumentException($"No unit found with SingularName equal to BaseUnit [{_quantity.BaseUnit}]. This unit must be defined.",
+ nameof(quantity));
+ _unitEnumName = $"{quantity.Name}Unit";
+ }
+
+ public override string Generate()
+ {
+ var baseUnitVariableName = _baseUnit.SingularName.ToLowerInvariant();
+
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL($@"
+using System;
+using System.Linq;
+using UnitsNet.Units;
+using Xunit;
+
+// Disable build warning CS1718: Comparison made to same variable; did you mean to compare something else?
+#pragma warning disable 1718
+
+// ReSharper disable once CheckNamespace
+namespace UnitsNet.Tests
+{{
+ ///
+ /// Test of {_quantity.Name}.
+ ///
+// ReSharper disable once PartialTypeWithSinglePart
+ public abstract partial class {_quantity.Name}TestsBase
+ {{");
+ foreach (var unit in _quantity.Units) Writer.WL($@"
+ protected abstract double {unit.PluralName}InOne{_baseUnit.SingularName} {{ get; }}");
+
+ Writer.WL("");
+ Writer.WL($@"
+// ReSharper disable VirtualMemberNeverOverriden.Global");
+ foreach (var unit in _quantity.Units) Writer.WL($@"
+ protected virtual double {unit.PluralName}Tolerance {{ get {{ return 1e-5; }} }}"); Writer.WL($@"
+// ReSharper restore VirtualMemberNeverOverriden.Global
+
+ [Fact]
+ public void Ctor_WithUndefinedUnit_ThrowsArgumentException()
+ {{
+ Assert.Throws(() => new {_quantity.Name}(({_quantity.BaseType})0.0, {_unitEnumName}.Undefined));
+ }}
+");
+ if (_quantity.BaseType == "double") Writer.WL($@"
+ [Fact]
+ public void Ctor_WithInfinityValue_ThrowsArgumentException()
+ {{
+ Assert.Throws(() => new {_quantity.Name}(double.PositiveInfinity, {_unitEnumName}.{_baseUnit.SingularName}));
+ Assert.Throws(() => new {_quantity.Name}(double.NegativeInfinity, {_unitEnumName}.{_baseUnit.SingularName}));
+ }}
+
+ [Fact]
+ public void Ctor_WithNaNValue_ThrowsArgumentException()
+ {{
+ Assert.Throws(() => new {_quantity.Name}(double.NaN, {_unitEnumName}.{_baseUnit.SingularName}));
+ }}
+"); Writer.WL($@"
+
+ [Fact]
+ public void {_baseUnit.SingularName}To{_quantity.Name}Units()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);");
+
+ foreach (var unit in _quantity.Units) Writer.WL($@"
+ AssertEx.EqualTolerance({unit.PluralName}InOne{_baseUnit.SingularName}, {baseUnitVariableName}.{unit.PluralName}, {unit.PluralName}Tolerance);");
+ Writer.WL($@"
+ }}
+
+ [Fact]
+ public void FromValueAndUnit()
+ {{");
+ foreach (var unit in _quantity.Units) Writer.WL($@"
+ AssertEx.EqualTolerance(1, {_quantity.Name}.From(1, {_unitEnumName}.{unit.SingularName}).{unit.PluralName}, {unit.PluralName}Tolerance);");
+ Writer.WL($@"
+ }}
+");
+ if (_quantity.BaseType == "double") Writer.WL($@"
+ [Fact]
+ public void From{_baseUnit.PluralName}_WithInfinityValue_ThrowsArgumentException()
+ {{
+ Assert.Throws(() => {_quantity.Name}.From{_baseUnit.PluralName}(double.PositiveInfinity));
+ Assert.Throws(() => {_quantity.Name}.From{_baseUnit.PluralName}(double.NegativeInfinity));
+ }}
+
+ [Fact]
+ public void From{_baseUnit.PluralName}_WithNanValue_ThrowsArgumentException()
+ {{
+ Assert.Throws(() => {_quantity.Name}.From{_baseUnit.PluralName}(double.NaN));
+ }}
+"); Writer.WL($@"
+
+ [Fact]
+ public void As()
+ {{
+ var {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);");
+ foreach (var unit in _quantity.Units) Writer.WL($@"
+ AssertEx.EqualTolerance({unit.PluralName}InOne{_baseUnit.SingularName}, {baseUnitVariableName}.As({_unitEnumName}.{unit.SingularName}), {unit.PluralName}Tolerance);");
+ Writer.WL($@"
+ }}
+
+ [Fact]
+ public void ToUnit()
+ {{
+ var {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);");
+ foreach (var unit in _quantity.Units)
+ {
+ var asQuantityVariableName = $"{unit.SingularName.ToLowerInvariant()}Quantity";
+
+ Writer.WL("");
+ Writer.WL($@"
+ var {asQuantityVariableName} = {baseUnitVariableName}.ToUnit({_unitEnumName}.{unit.SingularName});
+ AssertEx.EqualTolerance({unit.PluralName}InOne{_baseUnit.SingularName}, (double){asQuantityVariableName}.Value, {unit.PluralName}Tolerance);
+ Assert.Equal({_unitEnumName}.{unit.SingularName}, {asQuantityVariableName}.Unit);");
+ }
+ Writer.WL($@"
+ }}
+
+ [Fact]
+ public void ConversionRoundTrip()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);");
+ foreach (var unit in _quantity.Units) Writer.WL($@"
+ AssertEx.EqualTolerance(1, {_quantity.Name}.From{unit.PluralName}({baseUnitVariableName}.{unit.PluralName}).{_baseUnit.PluralName}, {unit.PluralName}Tolerance);");
+ Writer.WL($@"
+ }}
+");
+ if (_quantity.Logarithmic)
+ {
+ var unit = _quantity.Units.Last();
+ Writer.WL($@"
+ [Fact]
+ public void LogarithmicArithmeticOperators()
+ {{
+ {_quantity.Name} v = {_quantity.Name}.From{_baseUnit.PluralName}(40);
+ AssertEx.EqualTolerance(-40, -v.{_baseUnit.PluralName}, {unit.PluralName}Tolerance);
+ AssertLogarithmicAddition();
+ AssertLogarithmicSubtraction();
+ AssertEx.EqualTolerance(50, (v*10).{_baseUnit.PluralName}, {unit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(50, (10*v).{_baseUnit.PluralName}, {unit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(35, (v/5).{_baseUnit.PluralName}, {unit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(35, v/{_quantity.Name}.From{_baseUnit.PluralName}(5), {unit.PluralName}Tolerance);
+ }}
+
+ protected abstract void AssertLogarithmicAddition();
+
+ protected abstract void AssertLogarithmicSubtraction();
+");
+ }
+ else if (_quantity.GenerateArithmetic)
+ {
+ Writer.WL($@"
+ [Fact]
+ public void ArithmeticOperators()
+ {{
+ {_quantity.Name} v = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ AssertEx.EqualTolerance(-1, -v.{_baseUnit.PluralName}, {_baseUnit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(2, ({_quantity.Name}.From{_baseUnit.PluralName}(3)-v).{_baseUnit.PluralName}, {_baseUnit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(2, (v + v).{_baseUnit.PluralName}, {_baseUnit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(10, (v*10).{_baseUnit.PluralName}, {_baseUnit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(10, (10*v).{_baseUnit.PluralName}, {_baseUnit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(2, ({_quantity.Name}.From{_baseUnit.PluralName}(10)/5).{_baseUnit.PluralName}, {_baseUnit.PluralName}Tolerance);
+ AssertEx.EqualTolerance(2, {_quantity.Name}.From{_baseUnit.PluralName}(10)/{_quantity.Name}.From{_baseUnit.PluralName}(5), {_baseUnit.PluralName}Tolerance);
+ }}
+");
+ }
+ else
+ {
+ Writer.WL("");
+ }
+
+ Writer.WL($@"
+ [Fact]
+ public void ComparisonOperators()
+ {{
+ {_quantity.Name} one{_baseUnit.SingularName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ {_quantity.Name} two{_baseUnit.PluralName} = {_quantity.Name}.From{_baseUnit.PluralName}(2);
+
+ Assert.True(one{_baseUnit.SingularName} < two{_baseUnit.PluralName});
+ Assert.True(one{_baseUnit.SingularName} <= two{_baseUnit.PluralName});
+ Assert.True(two{_baseUnit.PluralName} > one{_baseUnit.SingularName});
+ Assert.True(two{_baseUnit.PluralName} >= one{_baseUnit.SingularName});
+
+ Assert.False(one{_baseUnit.SingularName} > two{_baseUnit.PluralName});
+ Assert.False(one{_baseUnit.SingularName} >= two{_baseUnit.PluralName});
+ Assert.False(two{_baseUnit.PluralName} < one{_baseUnit.SingularName});
+ Assert.False(two{_baseUnit.PluralName} <= one{_baseUnit.SingularName});
+ }}
+
+ [Fact]
+ public void CompareToIsImplemented()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ Assert.Equal(0, {baseUnitVariableName}.CompareTo({baseUnitVariableName}));
+ Assert.True({baseUnitVariableName}.CompareTo({_quantity.Name}.Zero) > 0);
+ Assert.True({_quantity.Name}.Zero.CompareTo({baseUnitVariableName}) < 0);
+ }}
+
+ [Fact]
+ public void CompareToThrowsOnTypeMismatch()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ Assert.Throws(() => {baseUnitVariableName}.CompareTo(new object()));
+ }}
+
+ [Fact]
+ public void CompareToThrowsOnNull()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ Assert.Throws(() => {baseUnitVariableName}.CompareTo(null));
+ }}
+
+ [Fact]
+ public void EqualityOperators()
+ {{
+ var a = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ var b = {_quantity.Name}.From{_baseUnit.PluralName}(2);
+
+ // ReSharper disable EqualExpressionComparison
+
+ Assert.True(a == a);
+ Assert.False(a != a);
+
+ Assert.True(a != b);
+ Assert.False(a == b);
+
+ Assert.False(a == null);
+ Assert.False(null == a);
+
+// ReSharper restore EqualExpressionComparison
+ }}
+
+ [Fact]
+ public void EqualsIsImplemented()
+ {{
+ var a = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ var b = {_quantity.Name}.From{_baseUnit.PluralName}(2);
+
+ Assert.True(a.Equals(a));
+ Assert.False(a.Equals(b));
+ Assert.False(a.Equals(null));
+ }}
+
+ [Fact]
+ public void EqualsRelativeToleranceIsImplemented()
+ {{
+ var v = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ Assert.True(v.Equals({_quantity.Name}.From{_baseUnit.PluralName}(1), {_baseUnit.PluralName}Tolerance, ComparisonType.Relative));
+ Assert.False(v.Equals({_quantity.Name}.Zero, {_baseUnit.PluralName}Tolerance, ComparisonType.Relative));
+ }}
+
+ [Fact]
+ public void EqualsReturnsFalseOnTypeMismatch()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ Assert.False({baseUnitVariableName}.Equals(new object()));
+ }}
+
+ [Fact]
+ public void EqualsReturnsFalseOnNull()
+ {{
+ {_quantity.Name} {baseUnitVariableName} = {_quantity.Name}.From{_baseUnit.PluralName}(1);
+ Assert.False({baseUnitVariableName}.Equals(null));
+ }}
+
+ [Fact]
+ public void UnitsDoesNotContainUndefined()
+ {{
+ Assert.DoesNotContain({_unitEnumName}.Undefined, {_quantity.Name}.Units);
+ }}
+
+ [Fact]
+ public void HasAtLeastOneAbbreviationSpecified()
+ {{
+ var units = Enum.GetValues(typeof({_unitEnumName})).Cast<{_unitEnumName}>();
+ foreach(var unit in units)
+ {{
+ if(unit == {_unitEnumName}.Undefined)
+ continue;
+
+ var defaultAbbreviation = UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit);
+ }}
+ }}
+
+ [Fact]
+ public void BaseDimensionsShouldNeverBeNull()
+ {{
+ Assert.False({_quantity.Name}.BaseDimensions is null);
+ }}
+ }}
+}}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGen/UnitTestStubGenerator.cs b/CodeGen/Generators/UnitsNetGen/UnitTestStubGenerator.cs
new file mode 100644
index 0000000000..3580502e0b
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/UnitTestStubGenerator.cs
@@ -0,0 +1,30 @@
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class UnitTestStubGenerator : GeneratorBase
+ {
+ private readonly Quantity _quantity;
+
+ public UnitTestStubGenerator(Quantity quantity)
+ {
+ _quantity = quantity;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL($@"
+using System;
+
+namespace UnitsNet.Tests.CustomCode
+{{
+ public class {_quantity.Name}Tests : {_quantity.Name}TestsBase
+ {{
+ // Override properties in base class here
+ }}
+}}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGen/UnitTypeGenerator.cs b/CodeGen/Generators/UnitsNetGen/UnitTypeGenerator.cs
new file mode 100644
index 0000000000..eaf6220511
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGen/UnitTypeGenerator.cs
@@ -0,0 +1,61 @@
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetGen
+{
+ internal class UnitTypeGenerator : GeneratorBase
+ {
+ private readonly Quantity _quantity;
+ private readonly string _unitEnumName;
+
+ public UnitTypeGenerator(Quantity quantity)
+ {
+ _quantity = quantity;
+ _unitEnumName = $"{quantity.Name}Unit";
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL($@"
+// ReSharper disable once CheckNamespace
+namespace UnitsNet.Units
+{{
+ // Disable missing XML comment warnings for the generated unit enums.
+ #pragma warning disable 1591
+
+ public enum {_unitEnumName}
+ {{
+ Undefined = 0,");
+
+ foreach (var unit in _quantity.Units)
+ {
+ if (unit.XmlDocSummary.HasText())
+ {
+ Writer.WL();
+ Writer.WL($@"
+ ///
+ /// {unit.XmlDocSummary}
+ /// ");
+ }
+
+ if (unit.XmlDocRemarks.HasText())
+ {
+ Writer.WL($@"
+ /// {unit.XmlDocRemarks}");
+ }
+
+ Writer.WLIfText(2, QuantityGenerator.GetObsoleteAttributeOrNull(unit));
+ Writer.WL($@"
+ {unit.SingularName},");
+ }
+
+ Writer.WL($@"
+ }}
+
+ #pragma warning restore 1591
+}}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetGenerator.cs b/CodeGen/Generators/UnitsNetGenerator.cs
new file mode 100644
index 0000000000..0155b07462
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetGenerator.cs
@@ -0,0 +1,267 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using CodeGen.Generators.UnitsNetGen;
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Serilog;
+
+namespace CodeGen.Generators
+{
+ internal static class UnitsNetGenerator
+ {
+ private const int AlignPad = 35;
+
+ private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings
+ {
+ // Don't override the C# default assigned values if no value is set in JSON
+ NullValueHandling = NullValueHandling.Ignore
+ };
+
+ public static void Generate(DirectoryInfo repositoryRoot)
+ {
+ if (repositoryRoot == null) throw new ArgumentNullException(nameof(repositoryRoot));
+ var root = repositoryRoot.FullName;
+
+ var templatesDir = Path.Combine(root, "Common/UnitDefinitions");
+ var jsonFiles = Directory.GetFiles(templatesDir, "*.json");
+ var quantities = jsonFiles.Select(ParseQuantityFile).ToArray();
+
+ foreach (Quantity quantity in quantities)
+ {
+ var sb = new StringBuilder($"{quantity.Name}:".PadRight(AlignPad));
+ GenerateQuantity(sb, quantity, $"{root}/UnitsNet/GeneratedCode/Quantities/{quantity.Name}.NetFramework.g.cs"); // TODO Remove NetFramework suffix
+ GenerateUnitType(sb, quantity, $"{root}/UnitsNet/GeneratedCode/Units/{quantity.Name}Unit.g.cs");
+ GenerateUnitTestBaseClass(sb, quantity, $"{root}/UnitsNet.Tests/GeneratedCode/{quantity.Name}TestsBase.g.cs");
+ GenerateUnitTestClassIfNotExists(sb, quantity, $"{root}/UnitsNet.Tests/CustomCode/{quantity.Name}Tests.cs");
+ Log.Information(sb.ToString());
+ }
+
+ Log.Information("");
+ GenerateUnitAbbreviationsCache(quantities, $"{root}/UnitsNet/GeneratedCode/UnitAbbreviationsCache.g.cs");
+ GenerateQuantityType(quantities, $"{root}/UnitsNet/GeneratedCode/QuantityType.g.cs");
+ GenerateStaticQuantity(quantities, $"{root}/UnitsNet/GeneratedCode/Quantity.g.cs");
+
+ var unitCount = quantities.SelectMany(q => q.Units).Count();
+ Log.Information("");
+ Log.Information($"Total of {unitCount} units and {quantities.Length} quantities.");
+ Log.Information("");
+ }
+
+ private static Quantity ParseQuantityFile(string jsonFile)
+ {
+ var quantity = JsonConvert.DeserializeObject(File.ReadAllText(jsonFile, Encoding.UTF8), JsonSerializerSettings);
+ AddPrefixUnits(quantity);
+ FixConversionFunctionsForDecimalValueTypes(quantity);
+ OrderUnitsByName(quantity);
+ return quantity;
+ }
+
+ private static void GenerateUnitTestClassIfNotExists(StringBuilder sb, Quantity quantity, string filePath)
+ {
+ if (File.Exists(filePath))
+ {
+ sb.Append("test stub(skip) ");
+ return;
+ }
+
+ string content = new UnitTestStubGenerator(quantity).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ sb.Append("test stub(OK) ");
+ }
+
+ private static void GenerateQuantity(StringBuilder sb, Quantity quantity, string filePath)
+ {
+ string content = new QuantityGenerator(quantity).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ sb.Append("quantity(OK) ");
+ }
+
+ private static void GenerateUnitType(StringBuilder sb, Quantity quantity, string filePath)
+ {
+ string content = new UnitTypeGenerator(quantity).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ sb.Append("unit(OK) ");
+ }
+
+ private static void GenerateUnitTestBaseClass(StringBuilder sb, Quantity quantity, string filePath)
+ {
+ string content = new UnitTestBaseClassGenerator(quantity).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ sb.Append("test base(OK) ");
+ }
+
+ private static void GenerateUnitAbbreviationsCache(Quantity[] quantities, string filePath)
+ {
+ string content = new UnitAbbreviationsCacheGenerator(quantities).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ Log.Information("UnitAbbreviationsCache.g.cs: ".PadRight(AlignPad) + "(OK)");
+ }
+
+ private static void GenerateQuantityType(Quantity[] quantities, string filePath)
+ {
+ string content = new QuantityTypeGenerator(quantities).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ Log.Information("QuantityType.g.cs: ".PadRight(AlignPad) + "(OK)");
+ }
+
+ private static void GenerateStaticQuantity(Quantity[] quantities, string filePath)
+ {
+ string content = new StaticQuantityGenerator(quantities).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ Log.Information("Quantity.g.cs: ".PadRight(AlignPad) + "(OK)");
+ }
+
+ private static void OrderUnitsByName(Quantity quantity)
+ {
+ quantity.Units = quantity.Units.OrderBy(u => u.SingularName).ToArray();
+ }
+
+ private static void FixConversionFunctionsForDecimalValueTypes(Quantity quantity)
+ {
+ foreach (Unit u in quantity.Units)
+ {
+ // Use decimal for internal calculations if base type is not double, such as for long or int.
+ if (string.Equals(quantity.BaseType, "decimal", StringComparison.OrdinalIgnoreCase))
+ {
+ // Change any double literals like "1024d" to decimal literals "1024m"
+ u.FromUnitToBaseFunc = u.FromUnitToBaseFunc.Replace("d", "m");
+ u.FromBaseToUnitFunc = u.FromBaseToUnitFunc.Replace("d", "m");
+ }
+ }
+ }
+
+ private static void AddPrefixUnits(Quantity quantity)
+ {
+ var unitsToAdd = new List();
+ foreach (Unit unit in quantity.Units)
+ {
+ // "Kilo", "Nano" etc.
+ for (var prefixIndex = 0; prefixIndex < unit.Prefixes.Length; prefixIndex++)
+ {
+ Prefix prefix = unit.Prefixes[prefixIndex];
+ PrefixInfo prefixInfo = PrefixInfo.Entries[prefix];
+
+ unitsToAdd.Add(new Unit
+ {
+ SingularName = $"{prefix}{unit.SingularName.ToCamelCase()}", // "Kilo" + "NewtonPerMeter" => "KilonewtonPerMeter"
+ PluralName = $"{prefix}{unit.PluralName.ToCamelCase()}", // "Kilo" + "NewtonsPerMeter" => "KilonewtonsPerMeter"
+ BaseUnits = null, // Can we determine this somehow?
+ FromBaseToUnitFunc = $"({unit.FromBaseToUnitFunc}) / {prefixInfo.Factor}",
+ FromUnitToBaseFunc = $"({unit.FromUnitToBaseFunc}) * {prefixInfo.Factor}",
+ Localization = GetLocalizationForPrefixUnit(unit, prefixIndex, prefixInfo, quantity.Name),
+ });
+ }
+ }
+
+ quantity.Units = quantity.Units.Concat(unitsToAdd).ToArray();
+ }
+
+ private static Localization[] GetLocalizationForPrefixUnit(Unit unit, int prefixIndex, PrefixInfo prefixInfo, string quantityName)
+ {
+ string[] GetUnitAbbreviationsForPrefix(Localization loc)
+ {
+ // If no custom abbreviations are specified, prepend the default prefix to each unit abbreviation: kilo ("k") + meter ("m") => kilometer ("km")
+ if (loc.AbbreviationsWithPrefixes == null || !loc.AbbreviationsWithPrefixes.Any())
+ {
+ string prefix = prefixInfo.Abbreviation;
+ return loc.Abbreviations.Select(unitAbbreviation => $"{prefix}{unitAbbreviation}").ToArray();
+ }
+
+ /*
+ Prepend prefix to all abbreviations of a unit.
+ Some languages, like Russian, you can't simply prepend "k" for kilo prefix, so the prefix abbreviations must be explicitly defined
+ with AbbreviationsWithPrefixes.
+
+ Example 1 - Torque.Newtonmeter has only a single abbreviation in Russian, so AbbreviationsWithPrefixes is an array of strings mapped to each prefix
+
+ {
+ "SingularName": "NewtonMeter",
+ "PluralName": "NewtonMeters",
+ "FromUnitToBaseFunc": "x",
+ "FromBaseToUnitFunc": "x",
+ "Prefixes": [ "Kilo", "Mega" ],
+ "Localization": [
+ {
+ "Culture": "en-US",
+ "Abbreviations": [ "N·m" ]
+ },
+ {
+ "Culture": "ru-RU",
+ "Abbreviations": [ "Н·м" ],
+ "AbbreviationsWithPrefixes": [ "кН·м", "МН·м" ]
+ }
+ ]
+ },
+
+ Example 2 - Duration.Second has 3 prefixes and 2 abbreviations in Russian, so AbbreviationsWithPrefixes is an array of 3 items where each
+ represents the unit abbreviations for that prefix - typically a variant of those in "Abbreviations", but the counts don't have to match.
+
+ {
+ "SingularName": "Second",
+ "PluralName": "Seconds",
+ "BaseUnits": {
+ "T": "Second"
+ },
+ "FromUnitToBaseFunc": "x",
+ "FromBaseToUnitFunc": "x",
+ "Prefixes": [ "Nano", "Micro", "Milli" ],
+ "Localization": [
+ {
+ "Culture": "en-US",
+ "Abbreviations": [ "s", "sec", "secs", "second", "seconds" ]
+ },
+ {
+ "Culture": "ru-RU",
+ "Abbreviations": [ "с", "сек" ],
+ "AbbreviationsWithPrefixes": [ ["нс", "нсек"], ["мкс", "мксек"], ["мс", "мсек"] ]
+ }
+ ]
+ }
+ */
+
+ EnsureValidAbbreviationsWithPrefixes(loc, unit, quantityName);
+ JToken abbreviationsForPrefix = loc.AbbreviationsWithPrefixes[prefixIndex];
+ switch (abbreviationsForPrefix.Type)
+ {
+ case JTokenType.Array:
+ return abbreviationsForPrefix.ToObject();
+ case JTokenType.String:
+ return new[] {abbreviationsForPrefix.ToObject()};
+ default:
+ throw new NotSupportedException("Expect AbbreviationsWithPrefixes to be an array of strings or string arrays.");
+ }
+ }
+
+ Localization WithPrefixes(Localization loc)
+ {
+ string[] unitAbbreviationsForPrefix = GetUnitAbbreviationsForPrefix(loc);
+
+ return new Localization
+ {
+ Culture = loc.Culture,
+ Abbreviations = unitAbbreviationsForPrefix,
+ };
+ }
+
+ return unit.Localization.Select(WithPrefixes).ToArray();
+ }
+
+ private static void EnsureValidAbbreviationsWithPrefixes(Localization localization, Unit unit, string quantityName)
+ {
+ if (localization.AbbreviationsWithPrefixes.Length > 0 &&
+ localization.AbbreviationsWithPrefixes.Length != unit.Prefixes.Length)
+ {
+ throw new InvalidDataException(
+ $"The Prefixes array length {unit.Prefixes.Length} does not match Localization.AbbreviationsWithPrefixes array length {localization.AbbreviationsWithPrefixes.Length} for {quantityName}.{unit.SingularName}");
+ }
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetWrcGen/QuantityGenerator.cs b/CodeGen/Generators/UnitsNetWrcGen/QuantityGenerator.cs
new file mode 100644
index 0000000000..96067ffdcc
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetWrcGen/QuantityGenerator.cs
@@ -0,0 +1,750 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+using System.Linq;
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetWrcGen
+{
+ internal class QuantityGenerator : GeneratorBase
+ {
+ private readonly Quantity _quantity;
+
+ private readonly bool _isDimensionless;
+ private readonly string _unitEnumName;
+ private readonly string _valueType;
+ private readonly Unit _baseUnit;
+
+ public QuantityGenerator(Quantity quantity)
+ {
+ _quantity = quantity ?? throw new ArgumentNullException(nameof(quantity));
+
+ _baseUnit = quantity.Units.FirstOrDefault(u => u.SingularName == _quantity.BaseUnit) ??
+ throw new ArgumentException($"No unit found with SingularName equal to BaseUnit [{_quantity.BaseUnit}]. This unit must be defined.",
+ nameof(quantity));
+
+ _valueType = quantity.BaseType;
+ _unitEnumName = $"{quantity.Name}Unit";
+
+ BaseDimensions baseDimensions = quantity.BaseDimensions;
+ _isDimensionless = baseDimensions == null ||
+ baseDimensions.L == 0 &&
+ baseDimensions.M == 0 &&
+ baseDimensions.T == 0 &&
+ baseDimensions.I == 0 &&
+ baseDimensions.Θ == 0 &&
+ baseDimensions.N == 0 &&
+ baseDimensions.J == 0;
+
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+using System;
+using System.Globalization;
+using System.Linq;
+using JetBrains.Annotations;
+using UnitsNet.Units;
+using UnitsNet.InternalHelpers;
+
+// ReSharper disable once CheckNamespace
+
+namespace UnitsNet
+{");
+ Writer.WLIfText(1, GetObsoleteAttributeOrNull(_quantity));
+ Writer.WL($@"
+ ///
+ /// {_quantity.XmlDoc}
+ /// ");
+
+ Writer.WLCondition(_quantity.XmlDocRemarks.HasText(), $@"
+ ///
+ /// {_quantity.XmlDocRemarks}
+ /// ");
+
+ Writer.WL($@"
+ // Windows Runtime Component has constraints on public types: https://msdn.microsoft.com/en-us/library/br230301.aspx#Declaring types in Windows Runtime Components
+ // Public structures can't have any members other than public fields, and those fields must be value types or strings.
+ // Public classes must be sealed (NotInheritable in Visual Basic). If your programming model requires polymorphism, you can create a public interface and implement that interface on the classes that must be polymorphic.
+ public sealed partial class {_quantity.Name} : IQuantity
+ {{
+ ///
+ /// The numeric value this quantity was constructed with.
+ ///
+ private readonly {_quantity.BaseType} _value;
+
+ ///
+ /// The unit this quantity was constructed with.
+ ///
+ private readonly {_unitEnumName}? _unit;
+");
+ GenerateStaticConstructor();
+ GenerateInstanceConstructors();
+ GenerateStaticProperties();
+ GenerateProperties();
+ GenerateConversionProperties();
+ GenerateStaticMethods();
+ GenerateStaticFactoryMethods();
+ GenerateStaticParseMethods();
+ GenerateEqualityAndComparison();
+ GenerateConversionMethods();
+ GenerateToString();
+
+ Writer.WL($@"
+ private static IFormatProvider GetFormatProviderFromCultureName([CanBeNull] string cultureName)
+ {{
+ return cultureName != null ? new CultureInfo(cultureName) : (IFormatProvider)null;
+ }}
+ }}
+}}");
+ return Writer.ToString();
+ }
+
+ private void GenerateStaticConstructor()
+ {
+ var baseDimensions = _quantity.BaseDimensions;
+ Writer.WL($@"
+ static {_quantity.Name}()
+ {{");
+ Writer.WL(_isDimensionless
+ ? @"
+ BaseDimensions = BaseDimensions.Dimensionless;"
+ : $@"
+ BaseDimensions = new BaseDimensions({baseDimensions.L}, {baseDimensions.M}, {baseDimensions.T}, {baseDimensions.I}, {baseDimensions.Θ}, {baseDimensions.N}, {baseDimensions.J});");
+
+ Writer.WL($@"
+ Info = new QuantityInfo(QuantityType.{_quantity.Name}, Units.Cast().ToArray(), BaseUnit, Zero, BaseDimensions);
+ }}
+");
+ }
+
+ private void GenerateInstanceConstructors()
+ {
+ Writer.WL($@"
+ ///
+ /// Creates the quantity with a value of 0 in the base unit {_baseUnit.SingularName}.
+ ///
+ ///
+ /// Windows Runtime Component requires a default constructor.
+ ///
+ public {_quantity.Name}()
+ {{
+ _value = 0;
+ _unit = BaseUnit;
+ }}
+
+ ///
+ /// Creates the quantity with the given numeric value and unit.
+ ///
+ /// The numeric value to contruct this quantity with.
+ /// The unit representation to contruct this quantity with.
+ /// Value parameter cannot be named 'value' due to constraint when targeting Windows Runtime Component.
+ /// If value is NaN or Infinity.
+ private {_quantity.Name}({_quantity.BaseType} numericValue, {_unitEnumName} unit)
+ {{
+ if(unit == {_unitEnumName}.Undefined)
+ throw new ArgumentException(""The quantity can not be created with an undefined unit."", nameof(unit));
+");
+
+ Writer.WL(_quantity.BaseType == "double"
+ ? @"
+ _value = Guard.EnsureValidNumber(numericValue, nameof(numericValue));"
+ : @"
+ _value = numericValue;");
+ Writer.WL($@"
+ _unit = unit;
+ }}
+");
+ }
+
+ private void GenerateStaticProperties()
+ {
+ Writer.WL($@"
+ #region Static Properties
+
+ ///
+ /// Information about the quantity type, such as unit values and names.
+ ///
+ internal static QuantityInfo Info {{ get; }}
+
+ ///
+ /// The of this quantity.
+ ///
+ public static BaseDimensions BaseDimensions {{ get; }}
+
+ ///
+ /// The base unit of {_quantity.Name}, which is {_quantity.BaseUnit}. All conversions go via this value.
+ ///
+ public static {_unitEnumName} BaseUnit {{ get; }} = {_unitEnumName}.{_quantity.BaseUnit};
+
+ ///
+ /// Represents the largest possible value of {_quantity.Name}
+ ///
+ public static {_quantity.Name} MaxValue {{ get; }} = new {_quantity.Name}({_valueType}.MaxValue, BaseUnit);
+
+ ///
+ /// Represents the smallest possible value of {_quantity.Name}
+ ///
+ public static {_quantity.Name} MinValue {{ get; }} = new {_quantity.Name}({_valueType}.MinValue, BaseUnit);
+
+ ///
+ /// The of this quantity.
+ ///
+ public static QuantityType QuantityType {{ get; }} = QuantityType.{_quantity.Name};
+
+ ///
+ /// All units of measurement for the {_quantity.Name} quantity.
+ ///
+ public static {_unitEnumName}[] Units {{ get; }} = Enum.GetValues(typeof({_unitEnumName})).Cast<{_unitEnumName}>().Except(new {_unitEnumName}[]{{ {_unitEnumName}.Undefined }}).ToArray();
+
+ ///
+ /// Gets an instance of this quantity with a value of 0 in the base unit {_quantity.BaseUnit}.
+ ///
+ public static {_quantity.Name} Zero {{ get; }} = new {_quantity.Name}(0, BaseUnit);
+
+ #endregion
+");
+ }
+
+ private void GenerateProperties()
+ {
+ Writer.WL($@"
+ #region Properties
+
+ ///
+ /// The numeric value this quantity was constructed with.
+ ///
+ public double Value => Convert.ToDouble(_value);
+");
+
+ Writer.WL($@"
+ ///
+ object IQuantity.Unit => Unit;
+
+ ///
+ /// The unit this quantity was constructed with -or- if default ctor was used.
+ ///
+ public {_unitEnumName} Unit => _unit.GetValueOrDefault(BaseUnit);
+
+ internal QuantityInfo QuantityInfo => Info;
+
+ ///
+ /// The of this quantity.
+ ///
+ public QuantityType Type => {_quantity.Name}.QuantityType;
+
+ ///
+ /// The of this quantity.
+ ///
+ public BaseDimensions Dimensions => {_quantity.Name}.BaseDimensions;
+
+ #endregion
+");
+ }
+
+ private void GenerateConversionProperties()
+ {
+ Writer.WL(@"
+ #region Conversion Properties
+");
+ foreach (var unit in _quantity.Units)
+ {
+ Writer.WL($@"
+ ///
+ /// Get {_quantity.Name} in {unit.PluralName}.
+ /// ");
+ Writer.WLIfText(2, GetObsoleteAttributeOrNull(unit));
+ Writer.WL($@"
+ public double {unit.PluralName} => As({_unitEnumName}.{unit.SingularName});
+");
+ }
+
+ Writer.WL(@"
+
+ #endregion
+");
+ }
+
+ private void GenerateStaticMethods()
+ {
+ Writer.WL($@"
+
+ #region Static Methods
+
+ ///
+ /// Get unit abbreviation string.
+ ///
+ /// Unit to get abbreviation for.
+ /// Unit abbreviation string.
+ public static string GetAbbreviation({_unitEnumName} unit)
+ {{
+ return GetAbbreviation(unit, null);
+ }}
+
+ ///
+ /// Get unit abbreviation string.
+ ///
+ /// Unit to get abbreviation for.
+ /// Unit abbreviation string.
+ /// Name of culture (ex: ""en-US"") to use when parsing number and unit. Defaults to if null.
+ public static string GetAbbreviation({_quantity.Name}Unit unit, [CanBeNull] string cultureName)
+ {{
+ IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
+ return UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit, provider);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateStaticFactoryMethods()
+ {
+ Writer.WL(@"
+ #region Static Factory Methods
+");
+ foreach (var unit in _quantity.Units)
+ {
+ var valueParamName = unit.PluralName.ToLowerInvariant();
+ Writer.WL($@"
+ ///
+ /// Get {_quantity.Name} from {unit.PluralName}.
+ ///
+ /// If value is NaN or Infinity.");
+ Writer.WLIfText(2, GetObsoleteAttributeOrNull(unit));
+ Writer.WL($@"
+ [Windows.Foundation.Metadata.DefaultOverload]
+ public static {_quantity.Name} From{unit.PluralName}(double {valueParamName})
+ {{
+ {_valueType} value = ({_valueType}) {valueParamName};
+ return new {_quantity.Name}(value, {_unitEnumName}.{unit.SingularName});
+ }}");
+ }
+
+ Writer.WL();
+ Writer.WL($@"
+ ///
+ /// Dynamically convert from value and unit enum to .
+ ///
+ /// Value to convert from.
+ /// Unit to convert from.
+ /// {_quantity.Name} unit value.
+ // Fix name conflict with parameter ""value""
+ [return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName(""returnValue"")]
+ public static {_quantity.Name} From(double value, {_unitEnumName} fromUnit)
+ {{
+ return new {_quantity.Name}(({_valueType})value, fromUnit);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateStaticParseMethods()
+ {
+ Writer.WL($@"
+ #region Static Parse Methods
+
+ ///
+ /// Parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ ///
+ /// Expected string to have one or two pairs of quantity and unit in the format
+ /// ""<quantity> <unit>"". Eg. ""5.5 m"" or ""1ft 2in""
+ ///
+ ///
+ /// More than one unit is represented by the specified unit abbreviation.
+ /// Example: Volume.Parse(""1 cup"") will throw, because it can refer to any of
+ /// , and .
+ ///
+ ///
+ /// If anything else goes wrong, typically due to a bug or unhandled case.
+ /// We wrap exceptions in to allow you to distinguish
+ /// Units.NET exceptions from other exceptions.
+ ///
+ public static {_quantity.Name} Parse(string str)
+ {{
+ return Parse(str, null);
+ }}
+
+ ///
+ /// Parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ ///
+ /// Expected string to have one or two pairs of quantity and unit in the format
+ /// ""<quantity> <unit>"". Eg. ""5.5 m"" or ""1ft 2in""
+ ///
+ ///
+ /// More than one unit is represented by the specified unit abbreviation.
+ /// Example: Volume.Parse(""1 cup"") will throw, because it can refer to any of
+ /// , and .
+ ///
+ ///
+ /// If anything else goes wrong, typically due to a bug or unhandled case.
+ /// We wrap exceptions in to allow you to distinguish
+ /// Units.NET exceptions from other exceptions.
+ ///
+ /// Name of culture (ex: ""en-US"") to use when parsing number and unit. Defaults to if null.
+ public static {_quantity.Name} Parse(string str, [CanBeNull] string cultureName)
+ {{
+ IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
+ return QuantityParser.Default.Parse<{_quantity.Name}, {_unitEnumName}>(
+ str,
+ provider,
+ From);
+ }}
+
+ ///
+ /// Try to parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ /// Resulting unit quantity if successful.
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ public static bool TryParse([CanBeNull] string str, out {_quantity.Name} result)
+ {{
+ return TryParse(str, null, out result);
+ }}
+
+ ///
+ /// Try to parse a string with one or two quantities of the format ""<quantity> <unit>"".
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ /// Resulting unit quantity if successful.
+ /// True if successful, otherwise false.
+ ///
+ /// Length.Parse(""5.5 m"", new CultureInfo(""en-US""));
+ ///
+ /// Name of culture (ex: ""en-US"") to use when parsing number and unit. Defaults to if null.
+ public static bool TryParse([CanBeNull] string str, [CanBeNull] string cultureName, out {_quantity.Name} result)
+ {{
+ IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
+ return QuantityParser.Default.TryParse<{_quantity.Name}, {_unitEnumName}>(
+ str,
+ provider,
+ From,
+ out result);
+ }}
+
+ ///
+ /// Parse a unit string.
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.ParseUnit(""m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ /// Error parsing string.
+ public static {_unitEnumName} ParseUnit(string str)
+ {{
+ return ParseUnit(str, null);
+ }}
+
+ ///
+ /// Parse a unit string.
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ ///
+ /// Length.ParseUnit(""m"", new CultureInfo(""en-US""));
+ ///
+ /// The value of 'str' cannot be null.
+ /// Error parsing string.
+ /// Name of culture (ex: ""en-US"") to use when parsing number and unit. Defaults to if null.
+ public static {_unitEnumName} ParseUnit(string str, [CanBeNull] string cultureName)
+ {{
+ IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
+ return UnitParser.Default.Parse<{_unitEnumName}>(str, provider);
+ }}
+
+ public static bool TryParseUnit(string str, out {_unitEnumName} unit)
+ {{
+ return TryParseUnit(str, null, out unit);
+ }}
+
+ ///
+ /// Parse a unit string.
+ ///
+ /// String to parse. Typically in the form: {{number}} {{unit}}
+ /// The parsed unit if successful.
+ /// True if successful, otherwise false.
+ ///
+ /// Length.TryParseUnit(""m"", new CultureInfo(""en-US""));
+ ///
+ /// Name of culture (ex: ""en-US"") to use when parsing number and unit. Defaults to if null.
+ public static bool TryParseUnit(string str, [CanBeNull] string cultureName, out {_unitEnumName} unit)
+ {{
+ IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
+ return UnitParser.Default.TryParse<{_unitEnumName}>(str, provider, out unit);
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateEqualityAndComparison()
+ {
+ Writer.WL($@"
+ #region Equality / IComparable
+
+ public int CompareTo(object obj)
+ {{
+ if(obj is null) throw new ArgumentNullException(nameof(obj));
+ if(!(obj is {_quantity.Name} obj{_quantity.Name})) throw new ArgumentException(""Expected type {_quantity.Name}."", nameof(obj));
+
+ return CompareTo(obj{_quantity.Name});
+ }}
+
+ // Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
+ internal int CompareTo({_quantity.Name} other)
+ {{
+ return _value.CompareTo(other.AsBaseNumericType(this.Unit));
+ }}
+
+ [Windows.Foundation.Metadata.DefaultOverload]
+ public override bool Equals(object obj)
+ {{
+ if(obj is null || !(obj is {_quantity.Name} obj{_quantity.Name}))
+ return false;
+
+ return Equals(obj{_quantity.Name});
+ }}
+
+ public bool Equals({_quantity.Name} other)
+ {{
+ return _value.Equals(other.AsBaseNumericType(this.Unit));
+ }}
+
+ ///
+ ///
+ /// Compare equality to another {_quantity.Name} within the given absolute or relative tolerance.
+ ///
+ ///
+ /// Relative tolerance is defined as the maximum allowable absolute difference between this quantity's value and
+ /// as a percentage of this quantity's value. will be converted into
+ /// this quantity's unit for comparison. A relative tolerance of 0.01 means the absolute difference must be within +/- 1% of
+ /// this quantity's value to be considered equal.
+ ///
+ /// In this example, the two quantities will be equal if the value of b is within +/- 1% of a (0.02m or 2cm).
+ ///
+ /// var a = Length.FromMeters(2.0);
+ /// var b = Length.FromInches(50.0);
+ /// a.Equals(b, 0.01, ComparisonType.Relative);
+ ///
+ ///
+ ///
+ ///
+ /// Absolute tolerance is defined as the maximum allowable absolute difference between this quantity's value and
+ /// as a fixed number in this quantity's unit. will be converted into
+ /// this quantity's unit for comparison.
+ ///
+ /// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
+ ///
+ /// var a = Length.FromMeters(2.0);
+ /// var b = Length.FromInches(50.0);
+ /// a.Equals(b, 0.01, ComparisonType.Absolute);
+ ///
+ ///
+ ///
+ ///
+ /// Note that it is advised against specifying zero difference, due to the nature
+ /// of floating point operations and using System.Double internally.
+ ///
+ ///
+ /// The other quantity to compare to.
+ /// The absolute or relative tolerance value. Must be greater than or equal to 0.
+ /// The comparison type: either relative or absolute.
+ /// True if the absolute difference between the two values is not greater than the specified relative or absolute tolerance.
+ public bool Equals({_quantity.Name} other, double tolerance, ComparisonType comparisonType)
+ {{
+ if(tolerance < 0)
+ throw new ArgumentOutOfRangeException(""tolerance"", ""Tolerance must be greater than or equal to 0."");
+
+ double thisValue = (double)this.Value;
+ double otherValueInThisUnits = other.As(this.Unit);
+
+ return UnitsNet.Comparison.Equals(thisValue, otherValueInThisUnits, tolerance, comparisonType);
+ }}
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// A hash code for the current {_quantity.Name}.
+ public override int GetHashCode()
+ {{
+ return new {{ QuantityType, Value, Unit }}.GetHashCode();
+ }}
+
+ #endregion
+");
+ }
+
+ private void GenerateConversionMethods()
+ {
+ Writer.WL($@"
+ #region Conversion Methods
+
+ double IQuantity.As(object unit) => As(({_quantity.Name}Unit)unit);
+
+ ///
+ /// Convert to the unit representation .
+ ///
+ /// Value converted to the specified unit.
+ public double As({_unitEnumName} unit)
+ {{
+ if(Unit == unit)
+ return Convert.ToDouble(Value);
+
+ var converted = AsBaseNumericType(unit);
+ return Convert.ToDouble(converted);
+ }}
+
+ ///
+ /// Converts this {_quantity.Name} to another {_quantity.Name} with the unit representation .
+ ///
+ /// A {_quantity.Name} with the specified unit.
+ public {_quantity.Name} ToUnit({_unitEnumName} unit)
+ {{
+ var convertedValue = AsBaseNumericType(unit);
+ return new {_quantity.Name}(convertedValue, unit);
+ }}
+
+ ///
+ /// Converts the current value + unit to the base unit.
+ /// This is typically the first step in converting from one unit to another.
+ ///
+ /// The value in the base unit representation.
+ private {_valueType} AsBaseUnit()
+ {{
+ switch(Unit)
+ {{");
+ foreach (var unit in _quantity.Units)
+ {
+ var func = unit.FromUnitToBaseFunc.Replace("x", "_value");
+ Writer.WL($@"
+ case {_unitEnumName}.{unit.SingularName}: return {func};");
+ }
+
+ Writer.WL($@"
+ default:
+ throw new NotImplementedException($""Can not convert {{Unit}} to base units."");
+ }}
+ }}
+
+ private {_valueType} AsBaseNumericType({_unitEnumName} unit)
+ {{
+ if(Unit == unit)
+ return _value;
+
+ var baseUnitValue = AsBaseUnit();
+
+ switch(unit)
+ {{");
+ foreach (var unit in _quantity.Units)
+ {
+ var func = unit.FromBaseToUnitFunc.Replace("x", "baseUnitValue");
+ Writer.WL($@"
+ case {_unitEnumName}.{unit.SingularName}: return {func};");
+ }
+
+ Writer.WL(@"
+ default:
+ throw new NotImplementedException($""Can not convert {Unit} to {unit}."");
+ }
+ }
+
+ #endregion
+");
+ }
+
+ private void GenerateToString()
+ {
+ Writer.WL($@"
+ #region ToString Methods
+
+ ///
+ /// Get default string representation of value and unit.
+ ///
+ /// String representation.
+ public override string ToString()
+ {{
+ return ToString(null);
+ }}
+
+ ///
+ /// Get string representation of value and unit. Using two significant digits after radix.
+ ///
+ /// String representation.
+ /// Name of culture (ex: ""en-US"") to use for localization and number formatting. Defaults to if null.
+ public string ToString([CanBeNull] string cultureName)
+ {{
+ var provider = cultureName;
+ return ToString(provider, 2);
+ }}
+
+ ///
+ /// Get string representation of value and unit.
+ ///
+ /// The number of significant digits after the radix point.
+ /// String representation.
+ /// Name of culture (ex: ""en-US"") to use for localization and number formatting. Defaults to if null.
+ public string ToString(string cultureName, int significantDigitsAfterRadix)
+ {{
+ var provider = cultureName;
+ var value = Convert.ToDouble(Value);
+ var format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix);
+ return ToString(provider, format);
+ }}
+
+ ///
+ /// Get string representation of value and unit.
+ ///
+ /// String format to use. Default: ""{{0:0.##}} {{1}} for value and unit abbreviation respectively.""
+ /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1.
+ /// String representation.
+ /// Name of culture (ex: ""en-US"") to use for localization and number formatting. Defaults to if null.
+ public string ToString([CanBeNull] string cultureName, [NotNull] string format, [NotNull] params object[] args)
+ {{
+ var provider = GetFormatProviderFromCultureName(cultureName);
+ if (format == null) throw new ArgumentNullException(nameof(format));
+ if (args == null) throw new ArgumentNullException(nameof(args));
+
+ provider = provider ?? GlobalConfiguration.DefaultCulture;
+
+ var value = Convert.ToDouble(Value);
+ var formatArgs = UnitFormatter.GetFormatArgs(Unit, value, provider, args);
+ return string.Format(provider, format, formatArgs);
+ }}
+
+ #endregion
+");
+ }
+
+ ///
+ internal static string GetObsoleteAttributeOrNull(Quantity quantity) => GetObsoleteAttributeOrNull(quantity.ObsoleteText);
+
+ ///
+ internal static string GetObsoleteAttributeOrNull(Unit unit) => GetObsoleteAttributeOrNull(unit.ObsoleteText);
+
+ ///
+ /// Returns the Obsolete attribute if ObsoleteText has been defined on the JSON input - otherwise returns empty string
+ /// It is up to the consumer to wrap any padding/new lines in order to keep to correct indentation formats
+ ///
+ private static string GetObsoleteAttributeOrNull(string obsoleteText) => string.IsNullOrWhiteSpace(obsoleteText)
+ ? null
+ : $"[System.Obsolete({obsoleteText})]";
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetWrcGen/QuantityTypeGenerator.cs b/CodeGen/Generators/UnitsNetWrcGen/QuantityTypeGenerator.cs
new file mode 100644
index 0000000000..582b299d6a
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetWrcGen/QuantityTypeGenerator.cs
@@ -0,0 +1,39 @@
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetWrcGen
+{
+ internal class QuantityTypeGenerator : GeneratorBase
+ {
+ private readonly Quantity[] _quantities;
+
+ public QuantityTypeGenerator(Quantity[] quantities)
+ {
+ _quantities = quantities;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+// ReSharper disable once CheckNamespace
+namespace UnitsNet
+{
+ ///
+ /// Lists all generated quantities with the same name as the quantity struct type,
+ /// such as Length, Mass, Force etc.
+ /// This is useful for populating options in the UI, such as creating a generic conversion
+ /// tool with inputValue, quantityName, fromUnit and toUnit selectors.
+ ///
+ public enum QuantityType
+ {
+ Undefined = 0,");
+ foreach (var quantity in _quantities)
+ Writer.WL($@"
+ {quantity.Name},");
+ Writer.WL(@"
+ }
+}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetWrcGen/StaticQuantityGenerator.cs b/CodeGen/Generators/UnitsNetWrcGen/StaticQuantityGenerator.cs
new file mode 100644
index 0000000000..133a34850b
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetWrcGen/StaticQuantityGenerator.cs
@@ -0,0 +1,122 @@
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetWrcGen
+{
+ internal class StaticQuantityGenerator : GeneratorBase
+ {
+ private readonly Quantity[] _quantities;
+
+ public StaticQuantityGenerator(Quantity[] quantities)
+ {
+ _quantities = quantities;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+using System;
+using System.Linq;
+using JetBrains.Annotations;
+using UnitsNet.InternalHelpers;
+using UnitsNet.Units;
+
+namespace UnitsNet
+{
+ ///
+ /// Dynamically parse or construct quantities when types are only known at runtime.
+ ///
+ internal static partial class Quantity
+ {
+ ///
+ /// Try to dynamically construct a quantity.
+ ///
+ /// Numeric value.
+ /// Unit enum value.
+ /// The resulting quantity if successful, otherwise default.
+ /// True if successful with assigned the value, otherwise false.
+ internal static bool TryFrom(double value, Enum unit, out IQuantity quantity)
+ {
+ switch (unit)
+ {");
+ foreach (var quantity in _quantities)
+ {
+ var quantityName = quantity.Name;
+ var unitTypeName = $"{quantityName}Unit";
+ var unitValue = unitTypeName.ToCamelCase();
+ Writer.WL($@"
+ case {unitTypeName} {unitValue}:
+ quantity = {quantityName}.From(value, {unitValue});
+ return true;");
+ }
+
+ Writer.WL($@"
+ default:
+ {{
+ quantity = default(IQuantity);
+ return false;
+ }}
+ }}
+ }}
+
+ ///
+ internal static IQuantity Parse(Type quantityType, string quantityString) => Parse(null, quantityType, quantityString);
+
+ ///
+ /// Dynamically parse a quantity string representation.
+ ///
+ /// The format provider to use for lookup. Defaults to if null.
+ /// Type of quantity, such as .
+ /// Quantity string representation, such as ""1.5 kg"". Must be compatible with given quantity type.
+ /// The parsed quantity.
+ /// Type must be of type UnitsNet.IQuantity -or- Type is not a known quantity type.
+ internal static IQuantity Parse([CanBeNull] IFormatProvider formatProvider, Type quantityType, string quantityString)
+ {{
+ if (!typeof(IQuantity).Wrap().IsAssignableFrom(quantityType))
+ throw new ArgumentException($""Type {{quantityType}} must be of type UnitsNet.IQuantity."");
+
+ if (TryParse(formatProvider, quantityType, quantityString, out IQuantity quantity)) return quantity;
+
+ throw new ArgumentException($""Quantity string could not be parsed to quantity {{quantityType}}."");
+ }}
+
+ ///
+ internal static bool TryParse(Type quantityType, string quantityString, out IQuantity quantity) =>
+ TryParse(null, quantityType, quantityString, out quantity);
+
+ ///
+ /// Try to dynamically parse a quantity string representation.
+ ///
+ /// The format provider to use for lookup. Defaults to if null.
+ /// Type of quantity, such as .
+ /// Quantity string representation, such as ""1.5 kg"". Must be compatible with given quantity type.
+ /// The resulting quantity if successful, otherwise default.
+ /// The parsed quantity.
+ internal static bool TryParse([CanBeNull] IFormatProvider formatProvider, Type quantityType, string quantityString, out IQuantity quantity)
+ {{
+ quantity = default(IQuantity);
+
+ if (!typeof(IQuantity).Wrap().IsAssignableFrom(quantityType))
+ return false;
+
+ var parser = QuantityParser.Default;
+");
+ foreach (var quantity in _quantities)
+ {
+ Writer.WL($@"
+ if (quantityType == typeof({quantity.Name}))
+ return parser.TryParse<{quantity.Name}, {quantity.Name}Unit>(quantityString, formatProvider, {quantity.Name}.From, out quantity);
+");
+ }
+
+ Writer.WL($@"
+ throw new ArgumentException(
+ $""Type {{quantityType}} is not a known quantity type. Did you pass in a third-party quantity type defined outside UnitsNet library?"");
+ }}
+ }}
+}}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetWrcGen/UnitAbbreviationsCacheGenerator.cs b/CodeGen/Generators/UnitsNetWrcGen/UnitAbbreviationsCacheGenerator.cs
new file mode 100644
index 0000000000..5695ad777a
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetWrcGen/UnitAbbreviationsCacheGenerator.cs
@@ -0,0 +1,58 @@
+using System.Linq;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetWrcGen
+{
+ internal class UnitAbbreviationsCacheGenerator : GeneratorBase
+ {
+ private readonly Quantity[] _quantities;
+
+ public UnitAbbreviationsCacheGenerator(Quantity[] quantities)
+ {
+ _quantities = quantities;
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL(@"
+using System;
+using UnitsNet.Units;
+
+// ReSharper disable RedundantCommaInArrayInitializer
+// ReSharper disable once CheckNamespace
+namespace UnitsNet
+{
+ public sealed partial class UnitAbbreviationsCache
+ {
+ private static readonly (string CultureName, Type UnitType, int UnitValue, string[] UnitAbbreviations)[] GeneratedLocalizations
+ = new []
+ {");
+ foreach (var quantity in _quantities)
+ {
+ var unitEnumName = $"{quantity.Name}Unit";
+
+ foreach (var unit in quantity.Units)
+ {
+ foreach (var localization in unit.Localization)
+ {
+ var cultureName = localization.Culture;
+
+ // All units must have a unit abbreviation, so fallback to "" for units with no abbreviations defined in JSON
+ var abbreviationParams = localization.Abbreviations.Any()
+ ? string.Join(", ", localization.Abbreviations.Select(abbr => $"\"{abbr}\""))
+ : "\"\"";
+ Writer.WL($@"
+ (""{cultureName}"", typeof({unitEnumName}), (int){unitEnumName}.{unit.SingularName}, new string[]{{{abbreviationParams}}}),");
+ }
+ }
+ }
+
+ Writer.WL(@"
+ };
+ }
+}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetWrcGen/UnitTypeGenerator.cs b/CodeGen/Generators/UnitsNetWrcGen/UnitTypeGenerator.cs
new file mode 100644
index 0000000000..939d947a17
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetWrcGen/UnitTypeGenerator.cs
@@ -0,0 +1,61 @@
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+
+namespace CodeGen.Generators.UnitsNetWrcGen
+{
+ internal class UnitTypeGenerator : GeneratorBase
+ {
+ private readonly Quantity _quantity;
+ private readonly string _unitEnumName;
+
+ public UnitTypeGenerator(Quantity quantity)
+ {
+ _quantity = quantity;
+ _unitEnumName = $"{quantity.Name}Unit";
+ }
+
+ public override string Generate()
+ {
+ Writer.WL(GeneratedFileHeader);
+ Writer.WL($@"
+// ReSharper disable once CheckNamespace
+namespace UnitsNet.Units
+{{
+ // Disable missing XML comment warnings for the generated unit enums.
+ #pragma warning disable 1591
+
+ public enum {_unitEnumName}
+ {{
+ Undefined = 0,");
+
+ foreach (var unit in _quantity.Units)
+ {
+ if (unit.XmlDocSummary.HasText())
+ {
+ Writer.WL();
+ Writer.WL($@"
+ ///
+ /// {unit.XmlDocSummary}
+ /// ");
+ }
+
+ if (unit.XmlDocRemarks.HasText())
+ {
+ Writer.WL($@"
+ /// {unit.XmlDocRemarks}");
+ }
+
+ Writer.WLIfText(2, UnitsNetGen.QuantityGenerator.GetObsoleteAttributeOrNull(unit));
+ Writer.WL($@"
+ {unit.SingularName},");
+ }
+
+ Writer.WL($@"
+ }}
+
+ #pragma warning restore 1591
+}}");
+ return Writer.ToString();
+ }
+ }
+}
diff --git a/CodeGen/Generators/UnitsNetWrcGenerator.cs b/CodeGen/Generators/UnitsNetWrcGenerator.cs
new file mode 100644
index 0000000000..86c17de1d6
--- /dev/null
+++ b/CodeGen/Generators/UnitsNetWrcGenerator.cs
@@ -0,0 +1,250 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using CodeGen.Helpers;
+using CodeGen.JsonTypes;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Serilog;
+using QuantityGenerator = CodeGen.Generators.UnitsNetWrcGen.QuantityGenerator;
+using QuantityTypeGenerator = CodeGen.Generators.UnitsNetWrcGen.QuantityTypeGenerator;
+using StaticQuantityGenerator = CodeGen.Generators.UnitsNetWrcGen.StaticQuantityGenerator;
+using UnitAbbreviationsCacheGenerator = CodeGen.Generators.UnitsNetWrcGen.UnitAbbreviationsCacheGenerator;
+using UnitTypeGenerator = CodeGen.Generators.UnitsNetWrcGen.UnitTypeGenerator;
+
+namespace CodeGen.Generators
+{
+ internal static class UnitsNetWrcGenerator
+ {
+ private const int AlignPad = 35;
+
+ private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings
+ {
+ // Don't override the C# default assigned values if no value is set in JSON
+ NullValueHandling = NullValueHandling.Ignore
+ };
+
+ public static void Generate(DirectoryInfo repositoryRoot)
+ {
+ if (repositoryRoot == null) throw new ArgumentNullException(nameof(repositoryRoot));
+ var root = repositoryRoot.FullName;
+ var outputDir = $"{root}/UnitsNet.WindowsRuntimeComponent/GeneratedCode";
+
+ var templatesDir = Path.Combine(root, "Common/UnitDefinitions");
+ var jsonFiles = Directory.GetFiles(templatesDir, "*.json");
+ var quantities = jsonFiles.Select(ParseQuantityFile).ToArray();
+
+ foreach (Quantity quantity in quantities)
+ {
+ var sb = new StringBuilder($"{quantity.Name}:".PadRight(AlignPad));
+ GenerateQuantity(sb, quantity, $"{outputDir}/Quantities/{quantity.Name}.WindowsRuntimeComponent.g.cs");
+ GenerateUnitType(sb, quantity, $"{outputDir}/Units/{quantity.Name}Unit.g.cs");
+ Log.Information(sb.ToString());
+ }
+
+ Log.Information("");
+ GenerateUnitAbbreviationsCache(quantities, $"{outputDir}/UnitAbbreviationsCache.g.cs");
+ GenerateQuantityType(quantities, $"{outputDir}/QuantityType.g.cs");
+ GenerateStaticQuantity(quantities, $"{outputDir}/Quantity.g.cs");
+
+ var unitCount = quantities.SelectMany(q => q.Units).Count();
+ Log.Information("");
+ Log.Information($"Total of {unitCount} units and {quantities.Length} quantities.");
+ Log.Information("");
+ }
+
+ private static Quantity ParseQuantityFile(string jsonFile)
+ {
+ var quantity = JsonConvert.DeserializeObject(File.ReadAllText(jsonFile, Encoding.UTF8), JsonSerializerSettings);
+ AddPrefixUnits(quantity);
+ FixConversionFunctionsForDecimalValueTypes(quantity);
+ OrderUnitsByName(quantity);
+ return quantity;
+ }
+
+ private static void GenerateQuantity(StringBuilder sb, Quantity quantity, string filePath)
+ {
+ string content = new QuantityGenerator(quantity).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ sb.Append("quantity(OK) ");
+ }
+
+ private static void GenerateUnitType(StringBuilder sb, Quantity quantity, string filePath)
+ {
+ string content = new UnitTypeGenerator(quantity).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ sb.Append("unit(OK) ");
+ }
+
+ private static void GenerateUnitAbbreviationsCache(Quantity[] quantities, string filePath)
+ {
+ string content = new UnitAbbreviationsCacheGenerator(quantities).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ Log.Information("UnitAbbreviationsCache.g.cs: ".PadRight(AlignPad) + "(OK)");
+ }
+
+ private static void GenerateQuantityType(Quantity[] quantities, string filePath)
+ {
+ string content = new QuantityTypeGenerator(quantities).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ Log.Information("QuantityType.g.cs: ".PadRight(AlignPad) + "(OK)");
+ }
+
+ private static void GenerateStaticQuantity(Quantity[] quantities, string filePath)
+ {
+ string content = new StaticQuantityGenerator(quantities).Generate();
+ File.WriteAllText(filePath, content, Encoding.UTF8);
+ Log.Information("Quantity.g.cs: ".PadRight(AlignPad) + "(OK)");
+ }
+
+ private static void OrderUnitsByName(Quantity quantity)
+ {
+ quantity.Units = quantity.Units.OrderBy(u => u.SingularName).ToArray();
+ }
+
+ private static void FixConversionFunctionsForDecimalValueTypes(Quantity quantity)
+ {
+ foreach (Unit u in quantity.Units)
+ {
+ // Use decimal for internal calculations if base type is not double, such as for long or int.
+ if (string.Equals(quantity.BaseType, "decimal", StringComparison.OrdinalIgnoreCase))
+ {
+ // Change any double literals like "1024d" to decimal literals "1024m"
+ u.FromUnitToBaseFunc = u.FromUnitToBaseFunc.Replace("d", "m");
+ u.FromBaseToUnitFunc = u.FromBaseToUnitFunc.Replace("d", "m");
+ }
+ }
+ }
+
+ private static void AddPrefixUnits(Quantity quantity)
+ {
+ var unitsToAdd = new List();
+ foreach (Unit unit in quantity.Units)
+ {
+ // "Kilo", "Nano" etc.
+ for (var prefixIndex = 0; prefixIndex < unit.Prefixes.Length; prefixIndex++)
+ {
+ Prefix prefix = unit.Prefixes[prefixIndex];
+ PrefixInfo prefixInfo = PrefixInfo.Entries[prefix];
+
+ unitsToAdd.Add(new Unit
+ {
+ SingularName = $"{prefix}{unit.SingularName.ToCamelCase()}", // "Kilo" + "NewtonPerMeter" => "KilonewtonPerMeter"
+ PluralName = $"{prefix}{unit.PluralName.ToCamelCase()}", // "Kilo" + "NewtonsPerMeter" => "KilonewtonsPerMeter"
+ BaseUnits = null, // Can we determine this somehow?
+ FromBaseToUnitFunc = $"({unit.FromBaseToUnitFunc}) / {prefixInfo.Factor}",
+ FromUnitToBaseFunc = $"({unit.FromUnitToBaseFunc}) * {prefixInfo.Factor}",
+ Localization = GetLocalizationForPrefixUnit(unit, prefixIndex, prefixInfo, quantity.Name),
+ });
+ }
+ }
+
+ quantity.Units = quantity.Units.Concat(unitsToAdd).ToArray();
+ }
+
+ private static Localization[] GetLocalizationForPrefixUnit(Unit unit, int prefixIndex, PrefixInfo prefixInfo, string quantityName)
+ {
+ string[] GetUnitAbbreviationsForPrefix(Localization loc)
+ {
+ // If no custom abbreviations are specified, prepend the default prefix to each unit abbreviation: kilo ("k") + meter ("m") => kilometer ("km")
+ if (loc.AbbreviationsWithPrefixes == null || !loc.AbbreviationsWithPrefixes.Any())
+ {
+ string prefix = prefixInfo.Abbreviation;
+ return loc.Abbreviations.Select(unitAbbreviation => $"{prefix}{unitAbbreviation}").ToArray();
+ }
+
+ /*
+ Prepend prefix to all abbreviations of a unit.
+ Some languages, like Russian, you can't simply prepend "k" for kilo prefix, so the prefix abbreviations must be explicitly defined
+ with AbbreviationsWithPrefixes.
+
+ Example 1 - Torque.Newtonmeter has only a single abbreviation in Russian, so AbbreviationsWithPrefixes is an array of strings mapped to each prefix
+
+ {
+ "SingularName": "NewtonMeter",
+ "PluralName": "NewtonMeters",
+ "FromUnitToBaseFunc": "x",
+ "FromBaseToUnitFunc": "x",
+ "Prefixes": [ "Kilo", "Mega" ],
+ "Localization": [
+ {
+ "Culture": "en-US",
+ "Abbreviations": [ "N·m" ]
+ },
+ {
+ "Culture": "ru-RU",
+ "Abbreviations": [ "Н·м" ],
+ "AbbreviationsWithPrefixes": [ "кН·м", "МН·м" ]
+ }
+ ]
+ },
+
+ Example 2 - Duration.Second has 3 prefixes and 2 abbreviations in Russian, so AbbreviationsWithPrefixes is an array of 3 items where each
+ represents the unit abbreviations for that prefix - typically a variant of those in "Abbreviations", but the counts don't have to match.
+
+ {
+ "SingularName": "Second",
+ "PluralName": "Seconds",
+ "BaseUnits": {
+ "T": "Second"
+ },
+ "FromUnitToBaseFunc": "x",
+ "FromBaseToUnitFunc": "x",
+ "Prefixes": [ "Nano", "Micro", "Milli" ],
+ "Localization": [
+ {
+ "Culture": "en-US",
+ "Abbreviations": [ "s", "sec", "secs", "second", "seconds" ]
+ },
+ {
+ "Culture": "ru-RU",
+ "Abbreviations": [ "с", "сек" ],
+ "AbbreviationsWithPrefixes": [ ["нс", "нсек"], ["мкс", "мксек"], ["мс", "мсек"] ]
+ }
+ ]
+ }
+ */
+
+ EnsureValidAbbreviationsWithPrefixes(loc, unit, quantityName);
+ JToken abbreviationsForPrefix = loc.AbbreviationsWithPrefixes[prefixIndex];
+ switch (abbreviationsForPrefix.Type)
+ {
+ case JTokenType.Array:
+ return abbreviationsForPrefix.ToObject();
+ case JTokenType.String:
+ return new[] {abbreviationsForPrefix.ToObject()};
+ default:
+ throw new NotSupportedException("Expect AbbreviationsWithPrefixes to be an array of strings or string arrays.");
+ }
+ }
+
+ Localization WithPrefixes(Localization loc)
+ {
+ string[] unitAbbreviationsForPrefix = GetUnitAbbreviationsForPrefix(loc);
+
+ return new Localization
+ {
+ Culture = loc.Culture,
+ Abbreviations = unitAbbreviationsForPrefix,
+ };
+ }
+
+ return unit.Localization.Select(WithPrefixes).ToArray();
+ }
+
+ private static void EnsureValidAbbreviationsWithPrefixes(Localization localization, Unit unit, string quantityName)
+ {
+ if (localization.AbbreviationsWithPrefixes.Length > 0 &&
+ localization.AbbreviationsWithPrefixes.Length != unit.Prefixes.Length)
+ {
+ throw new InvalidDataException(
+ $"The Prefixes array length {unit.Prefixes.Length} does not match Localization.AbbreviationsWithPrefixes array length {localization.AbbreviationsWithPrefixes.Length} for {quantityName}.{unit.SingularName}");
+ }
+ }
+ }
+}
diff --git a/CodeGen/Helpers/MyTextWriter.cs b/CodeGen/Helpers/MyTextWriter.cs
new file mode 100644
index 0000000000..3fae829a09
--- /dev/null
+++ b/CodeGen/Helpers/MyTextWriter.cs
@@ -0,0 +1,109 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System.Linq;
+using System.Text;
+
+namespace CodeGen.Helpers
+{
+ internal class MyTextWriter
+ {
+ private readonly StringBuilder _sb = new StringBuilder();
+ private string _currentIndentationString;
+ private int _indentLevel;
+
+ public MyTextWriter(string indentString = " ", int initialIndentLevel = 0)
+ {
+ IndentString = indentString;
+ IndentLevel = initialIndentLevel;
+ }
+
+ public string IndentString { get; }
+
+ public int IndentLevel
+ {
+ get => _indentLevel;
+ set
+ {
+ _indentLevel = value;
+ _currentIndentationString = GetIndent(_indentLevel);
+ }
+ }
+
+ private string GetIndent(int indentLevel)
+ {
+ return string.Join(string.Empty, Enumerable.Repeat(IndentString, indentLevel));
+ }
+
+ ///
+ /// Write line with current indent. Trims preceding newline if any, to simplify code formatting when calling this method.
+ ///
+ /// The indent level to prepend the text with.
+ /// The text to write
+ public void WL(int indentLevel, string text = "")
+ {
+ _sb.Append(GetIndent(indentLevel));
+ _sb.AppendLine(text.TrimStart('\r', '\n'));
+ }
+
+ ///
+ /// Write line with current indent. Trims preceding newline if any, to simplify code formatting when calling this method.
+ ///
+ /// The text to write
+ public void WL(string text = "")
+ {
+ _sb.Append(_currentIndentationString);
+ _sb.AppendLine(text.TrimStart('\r', '\n'));
+ }
+
+ ///
+ /// Write with current indent, but no newline. Trims preceding newline if any, to simplify code formatting when calling this method.
+ ///
+ /// The text to write
+ public void W(string text = "")
+ {
+ _sb.Append(_currentIndentationString);
+ _sb.Append(text.TrimStart('\r', '\n'));
+ }
+
+ ///
+ /// Append text without indentation and without newline.
+ ///
+ /// The text to write
+ public void Append(string text = "")
+ {
+ _sb.Append(text);
+ }
+
+ ///
+ /// Returns the text written so far.
+ ///
+ ///
+ public override string ToString()
+ {
+ return _sb.ToString();
+ }
+
+ ///
+ /// Write line with current ident only if actually contains text and not just whitespace.
+ ///
+ /// The level of indentation to prepend to the text.
+ /// The text to write.
+ public void WLIfText(int indentLevel, string text)
+ {
+ if (string.IsNullOrWhiteSpace(text)) return;
+ WL(indentLevel, text);
+ }
+
+ ///
+ /// Write line with current ident only if is true.
+ ///
+ /// The condition.
+ /// The text to write.
+ public void WLCondition(bool condition, string text)
+ {
+ if (condition)
+ WL(text);
+ }
+ }
+}
diff --git a/CodeGen/Helpers/StringExtensions.cs b/CodeGen/Helpers/StringExtensions.cs
new file mode 100644
index 0000000000..9091491889
--- /dev/null
+++ b/CodeGen/Helpers/StringExtensions.cs
@@ -0,0 +1,21 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+namespace CodeGen.Helpers
+{
+ internal static class StringExtensions
+ {
+ ///
+ /// Returns true if string is not null and not whitespace.
+ ///
+ public static bool HasText(this string str) => !string.IsNullOrWhiteSpace(str);
+
+ ///
+ /// Example: "Kilo" + ToCamelCase("NewtonPerMeter") => "KilonewtonPerMeter"
+ ///
+ public static string ToCamelCase(this string str)
+ {
+ return char.ToLowerInvariant(str[0]) + str.Substring(1);
+ }
+ }
+}
diff --git a/CodeGen/JsonTypes/BaseDimensions.cs b/CodeGen/JsonTypes/BaseDimensions.cs
new file mode 100644
index 0000000000..a6caad21fd
--- /dev/null
+++ b/CodeGen/JsonTypes/BaseDimensions.cs
@@ -0,0 +1,29 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+namespace CodeGen.JsonTypes
+{
+ internal class BaseDimensions
+ {
+ // 0649 Field is never assigned to
+#pragma warning disable 0649
+
+ /// AmountOfSubstance.
+ public int N = 0;
+ /// ElectricCurrent.
+ public int I = 0;
+ /// Length.
+ public int L = 0;
+ /// LuminousIntensity.
+ public int J = 0;
+ /// Mass.
+ public int M = 0;
+ /// Temperature.
+ public int Θ = 0;
+ /// Time.
+ public int T = 0;
+
+ // 0649 Field is never assigned to
+#pragma warning restore 0649
+ }
+}
diff --git a/CodeGen/JsonTypes/BaseUnits.cs b/CodeGen/JsonTypes/BaseUnits.cs
new file mode 100644
index 0000000000..46f0887811
--- /dev/null
+++ b/CodeGen/JsonTypes/BaseUnits.cs
@@ -0,0 +1,29 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+namespace CodeGen.JsonTypes
+{
+ internal class BaseUnits
+ {
+ // 0649 Field is never assigned to
+#pragma warning disable 0649
+
+ /// AmountOfSubstance.
+ public string N;
+ /// ElectricCurrent.
+ public string I;
+ /// Length.
+ public string L;
+ /// LuminousIntensity.
+ public string J;
+ /// Mass.
+ public string M;
+ /// Temperature.
+ public string Θ;
+ /// Time.
+ public string T;
+
+ // 0649 Field is never assigned to
+#pragma warning restore 0649
+ }
+}
diff --git a/CodeGen/JsonTypes/Localization.cs b/CodeGen/JsonTypes/Localization.cs
new file mode 100644
index 0000000000..0419ca2e4f
--- /dev/null
+++ b/CodeGen/JsonTypes/Localization.cs
@@ -0,0 +1,21 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+using Newtonsoft.Json.Linq;
+
+namespace CodeGen.JsonTypes
+{
+ internal class Localization
+ {
+ // 0649 Field is never assigned to
+#pragma warning disable 0649
+
+ public string[] Abbreviations = Array.Empty();
+ public JToken[] AbbreviationsWithPrefixes;
+ public string Culture;
+
+ // 0649 Field is never assigned to
+#pragma warning restore 0649
+ }
+}
diff --git a/CodeGen/JsonTypes/Prefix.cs b/CodeGen/JsonTypes/Prefix.cs
new file mode 100644
index 0000000000..62d106bb39
--- /dev/null
+++ b/CodeGen/JsonTypes/Prefix.cs
@@ -0,0 +1,35 @@
+namespace CodeGen.JsonTypes
+{
+ internal enum Prefix
+ {
+ // SI prefixes
+ Yocto,
+ Zepto,
+ Atto,
+ Femto,
+ Pico,
+ Nano,
+ Micro,
+ Milli,
+ Centi,
+ Deci,
+ Deca,
+ Hecto,
+ Kilo,
+ Mega,
+ Giga,
+ Tera,
+ Peta,
+ Exa,
+ Zetta,
+ Yotta,
+
+ // Binary prefixes
+ Kibi,
+ Mebi,
+ Gibi,
+ Tebi,
+ Pebi,
+ Exbi
+ }
+}
\ No newline at end of file
diff --git a/CodeGen/JsonTypes/Quantity.cs b/CodeGen/JsonTypes/Quantity.cs
new file mode 100644
index 0000000000..0888bf8464
--- /dev/null
+++ b/CodeGen/JsonTypes/Quantity.cs
@@ -0,0 +1,29 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+using System.Collections.Generic;
+
+namespace CodeGen.JsonTypes
+{
+ internal class Quantity
+ {
+ // 0649 Field is never assigned to
+#pragma warning disable 0649
+
+ public BaseDimensions BaseDimensions = new BaseDimensions(); // Default to empty
+ public string BaseType = "double"; // TODO Rename to ValueType
+ public string BaseUnit; // TODO Rename to DefaultUnit or IntermediateConversionUnit to avoid confusion with Unit.BaseUnits
+ public bool GenerateArithmetic = true;
+ public bool Logarithmic = false;
+ public int LogarithmicScalingFactor = 1;
+ public string Name;
+ public Unit[] Units = Array.Empty();
+ public string XmlDocRemarks;
+ public string XmlDoc; // TODO Rename to XmlDocSummary
+ public string ObsoleteText;
+
+ // 0649 Field is never assigned to
+#pragma warning restore 0649
+ }
+}
diff --git a/CodeGen/JsonTypes/Unit.cs b/CodeGen/JsonTypes/Unit.cs
new file mode 100644
index 0000000000..b6d03feb9a
--- /dev/null
+++ b/CodeGen/JsonTypes/Unit.cs
@@ -0,0 +1,27 @@
+// Licensed under MIT No Attribution, see LICENSE file at the root.
+// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
+
+using System;
+
+namespace CodeGen.JsonTypes
+{
+ internal class Unit
+ {
+ // 0649 Field is never assigned to
+#pragma warning disable 0649
+
+ public BaseUnits BaseUnits;
+ public string FromBaseToUnitFunc;
+ public string FromUnitToBaseFunc;
+ public Localization[] Localization = Array.Empty();
+ public string PluralName;
+ public Prefix[] Prefixes = Array.Empty();
+ public string SingularName;
+ public string XmlDocRemarks;
+ public string XmlDocSummary;
+ public string ObsoleteText;
+
+ // 0649 Field is never assigned to
+#pragma warning restore 0649
+ }
+}
diff --git a/CodeGen/PrefixInfo.cs b/CodeGen/PrefixInfo.cs
new file mode 100644
index 0000000000..48eae0f539
--- /dev/null
+++ b/CodeGen/PrefixInfo.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using CodeGen.JsonTypes;
+
+namespace CodeGen
+{
+ ///
+ /// Information about a unit prefix and a static dictionary to look up prefixes.
+ ///
+ internal class PrefixInfo
+ {
+ ///
+ /// The unit prefix abbreviation, such as "k" for kilo or "m" for milli.
+ ///
+ public string Abbreviation { get; }
+
+ ///
+ /// C# expression for the multiplier to prefix the conversion function.
+ ///
+ /// Kilo has "1e3" in order to multiply by 1000.
+ public string Factor { get; }
+
+ public static readonly IReadOnlyDictionary Entries = new Dictionary
+ {
+ // NOTE: Need to append 'd' suffix for double in order to later search/replace "d" with "m"
+ // when creating decimal conversion functions in CodeGen.Generator.FixConversionFunctionsForDecimalValueTypes.
+
+ // SI prefixes
+ { Prefix.Yocto, new PrefixInfo("y", "1e-24d") },
+ { Prefix.Zepto, new PrefixInfo("z", "1e-21d") },
+ { Prefix.Atto, new PrefixInfo("a", "1e-18d") },
+ { Prefix.Femto, new PrefixInfo("f", "1e-15d") },
+ { Prefix.Pico, new PrefixInfo("p", "1e-12d") },
+ { Prefix.Nano, new PrefixInfo("n", "1e-9d") },
+ { Prefix.Micro, new PrefixInfo("µ", "1e-6d") },
+ { Prefix.Milli, new PrefixInfo("m", "1e-3d") },
+ { Prefix.Centi, new PrefixInfo("c", "1e-2d") },
+ { Prefix.Deci, new PrefixInfo("d", "1e-1d") },
+ { Prefix.Deca, new PrefixInfo("da", "1e1d") },
+ { Prefix.Hecto, new PrefixInfo("h", "1e2d") },
+ { Prefix.Kilo, new PrefixInfo("k", "1e3d") },
+ { Prefix.Mega, new PrefixInfo("M", "1e6d") },
+ { Prefix.Giga, new PrefixInfo("G", "1e9d") },
+ { Prefix.Tera, new PrefixInfo("T", "1e12d") },
+ { Prefix.Peta, new PrefixInfo("P", "1e15d") },
+ { Prefix.Exa, new PrefixInfo("E", "1e18d") },
+ { Prefix.Zetta, new PrefixInfo("Z", "1e21d") },
+ { Prefix.Yotta, new PrefixInfo("Y", "1e24d") },
+
+ // Binary prefixes
+ { Prefix.Kibi, new PrefixInfo("Ki", $"1024d") },
+ { Prefix.Mebi, new PrefixInfo("Mi", $"(1024d * 1024)") },
+ { Prefix.Gibi, new PrefixInfo("Gi", $"(1024d * 1024 * 1024)") },
+ { Prefix.Tebi, new PrefixInfo("Ti", $"(1024d * 1024 * 1024 * 1024)") },
+ { Prefix.Pebi, new PrefixInfo("Pi", $"(1024d * 1024 * 1024 * 1024 * 1024)") },
+ { Prefix.Exbi, new PrefixInfo("Ei", $"(1024d * 1024 * 1024 * 1024 * 1024 * 1024)") },
+ };
+
+ private PrefixInfo(string abbreviation, string factor)
+ {
+ Abbreviation = abbreviation;
+ Factor = factor;
+ }
+ }
+}
diff --git a/CodeGen/Program.cs b/CodeGen/Program.cs
new file mode 100644
index 0000000000..baa428c7c8
--- /dev/null
+++ b/CodeGen/Program.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using CodeGen.Generators;
+using Serilog;
+using Serilog.Events;
+
+namespace CodeGen
+{
+ class Program
+ {
+ ///
+ /// Code generator for Units.NET.
+ /// Reads unit definitions from JSON files and outputs C# files in GeneratedCode folders:
+ ///
+ /// - Quantity types (Length, Mass, ...)
+ /// - enum type (QuantityType.Length, QuantityType.Mass, ...)
+ /// - type
+ ///
+ /// - Test stubs for testing conversion functions of all units, to be fleshed out by a human later
+ /// - Unit enum types (LengthUnit, MassUnit, ...)
+ ///
+ ///
+ ///
+ /// System.CommandLine.Dragonfruit based Main method, where CLI arguments are parsed and passed directly to this method.
+ /// See https://github.com/dotnet/command-line-api/
+ ///
+ /// Verbose output? Defaults to false.
+ /// The repository root directory, defaults to searching parent directories for UnitsNet.sln.
+ /// Skip generate UnitsNet.WindowsRuntimeComponent? Defaults to false.
+ static int Main(bool verbose = false, DirectoryInfo repositoryRoot = null, bool skipWrc = false)
+ {
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo
+ .Console(restrictedToMinimumLevel: verbose ? LogEventLevel.Verbose : LogEventLevel.Information)
+ .CreateLogger();
+
+ try
+ {
+ if (repositoryRoot == null)
+ {
+ var executableParentDir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
+ Log.Verbose($"Executable dir: {executableParentDir}");
+
+ if (!TryFindRepositoryRoot(executableParentDir, out repositoryRoot))
+ {
+ throw new Exception($"Unable to find repository root in directory hierarchy: {executableParentDir}");
+ }
+ }
+
+ var sw = Stopwatch.StartNew();
+ Log.Information($"Units.NET code generator {Assembly.GetExecutingAssembly().GetName().Version}", ConsoleColor.Green);
+ if (verbose)
+ {
+ Log.Debug($"verbose: {true}", ConsoleColor.Blue);
+ }
+
+ UnitsNetGenerator.Generate(repositoryRoot);
+
+ if (!skipWrc)
+ UnitsNetWrcGenerator.Generate(repositoryRoot);
+
+ Log.Information($"Completed in {sw.ElapsedMilliseconds} ms!", ConsoleColor.Green);
+ return 0;
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "Unexpected error.");
+ return 1;
+ }
+ }
+
+ private static bool TryFindRepositoryRoot(DirectoryInfo searchFromDir, out DirectoryInfo repoRootDir)
+ {
+ for (var dir = searchFromDir; dir != null; dir = dir.Parent)
+ {
+ if (dir.GetFiles("UnitsNet.sln").Any())
+ {
+ repoRootDir = dir;
+ Log.Verbose($"Found repo root: {dir}");
+ return true;
+ }
+
+ Log.Verbose($"Not repo root: {dir}");
+ }
+
+ Log.Verbose($"Giving up finding repo root.");
+ repoRootDir = null;
+ return false;
+ }
+ }
+}
diff --git a/CodeGen/README.md b/CodeGen/README.md
new file mode 100644
index 0000000000..121c50bd82
--- /dev/null
+++ b/CodeGen/README.md
@@ -0,0 +1,33 @@
+# Units.NET Code Generator
+This tool will replace the PowerShell scripts for generating source code.
+It is faster, easier to debug and more familiar to C# developers.
+
+## Generating code
+Compile and run:
+```cmd
+cd /dev/UnitsNet/CodeGen
+dotnet run
+```
+
+Alternatively, build the .exe and run it:
+```cmd
+cd /dev/UnitsNet/CodeGen
+dotnet publish -c Release -r win10-x64
+cd ../Artifacts/CodeGen/netcoreapp2.1/win10-x64/
+CodeGen.exe
+```
+
+## Bonus: .NET CLI Parameter Suggestions
+The new, experimental DragonFruit .NET Core console app model has a suggestion API to query parameters of .exe files in order to suggest or auto-complete like PowerShell does.
+To get parameter suggestions, follow the [instructions](https://github.com/dotnet/command-line-api/wiki/Features-overview#suggestions).
+
+PowerShell:
+```powershell
+cd /dev/UnitsNet/CodeGen
+dotnet publish -c Release -r win10-x64 CodeGen
+cd ../Artifacts/CodeGen/netcoreapp2.1/win10-x64/
+CodeGen.exe --ver
+```
+
+Hit TAB and it should now suggest `--version` and `--verbose` parameters.
+This should work with any .exe that is compiled with Dragonfruit's app model.
diff --git a/UnitsNet.Tests/GeneratedCode/InformationTestsBase.g.cs b/UnitsNet.Tests/GeneratedCode/InformationTestsBase.g.cs
index 41d1faad3b..9d1d4a362f 100644
--- a/UnitsNet.Tests/GeneratedCode/InformationTestsBase.g.cs
+++ b/UnitsNet.Tests/GeneratedCode/InformationTestsBase.g.cs
@@ -96,7 +96,6 @@ public void Ctor_WithUndefinedUnit_ThrowsArgumentException()
Assert.Throws(() => new Information((decimal)0.0, InformationUnit.Undefined));
}
-
[Fact]
public void BitToInformationUnits()
{
@@ -160,7 +159,6 @@ public void FromValueAndUnit()
AssertEx.EqualTolerance(1, Information.From(1, InformationUnit.Terabyte).Terabytes, TerabytesTolerance);
}
-
[Fact]
public void As()
{
diff --git a/UnitsNet.Tests/GeneratedCode/LevelTestsBase.g.cs b/UnitsNet.Tests/GeneratedCode/LevelTestsBase.g.cs
index 48c2a61dea..a0bb62b88a 100644
--- a/UnitsNet.Tests/GeneratedCode/LevelTestsBase.g.cs
+++ b/UnitsNet.Tests/GeneratedCode/LevelTestsBase.g.cs
@@ -136,7 +136,6 @@ public void LogarithmicArithmeticOperators()
protected abstract void AssertLogarithmicSubtraction();
-
[Fact]
public void ComparisonOperators()
{
diff --git a/UnitsNet.WindowsRuntimeComponent/GeneratedCode/UnitAbbreviationsCache.g.cs b/UnitsNet.WindowsRuntimeComponent/GeneratedCode/UnitAbbreviationsCache.g.cs
index fc54d544e3..e5d56fbb6d 100644
--- a/UnitsNet.WindowsRuntimeComponent/GeneratedCode/UnitAbbreviationsCache.g.cs
+++ b/UnitsNet.WindowsRuntimeComponent/GeneratedCode/UnitAbbreviationsCache.g.cs
@@ -71,18 +71,15 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Degree, new string[]{"°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Gradian, new string[]{"g"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Gradian, new string[]{"g"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µ°"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µdeg"}),
+ ("en-US", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µ°", "µdeg"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µ°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Microradian, new string[]{"µrad"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Microradian, new string[]{"µрад"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"m°"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"mdeg"}),
+ ("en-US", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"m°", "mdeg"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"m°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Milliradian, new string[]{"mrad"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Milliradian, new string[]{"mрад"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"n°"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"ndeg"}),
+ ("en-US", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"n°", "ndeg"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"n°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Nanoradian, new string[]{"nrad"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Nanoradian, new string[]{"nрад"}),
@@ -129,41 +126,29 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(AreaMomentOfInertiaUnit), (int)AreaMomentOfInertiaUnit.MillimeterToTheFourth, new string[]{"mm⁴", "mm^4"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.BitPerSecond, new string[]{"bit/s", "bps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.BytePerSecond, new string[]{"B/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabitPerSecond, new string[]{"Ebit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabitPerSecond, new string[]{"Ebps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabitPerSecond, new string[]{"Ebit/s", "Ebps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabytePerSecond, new string[]{"EB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibitPerSecond, new string[]{"Eibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibitPerSecond, new string[]{"Eibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibitPerSecond, new string[]{"Eibit/s", "Eibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibytePerSecond, new string[]{"EiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibitPerSecond, new string[]{"Gibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibitPerSecond, new string[]{"Gibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibitPerSecond, new string[]{"Gibit/s", "Gibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibytePerSecond, new string[]{"GiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabitPerSecond, new string[]{"Gbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabitPerSecond, new string[]{"Gbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabitPerSecond, new string[]{"Gbit/s", "Gbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabytePerSecond, new string[]{"GB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibitPerSecond, new string[]{"Kibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibitPerSecond, new string[]{"Kibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibitPerSecond, new string[]{"Kibit/s", "Kibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibytePerSecond, new string[]{"KiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobitPerSecond, new string[]{"kbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobitPerSecond, new string[]{"kbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobitPerSecond, new string[]{"kbit/s", "kbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobytePerSecond, new string[]{"kB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibitPerSecond, new string[]{"Mibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibitPerSecond, new string[]{"Mibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibitPerSecond, new string[]{"Mibit/s", "Mibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibytePerSecond, new string[]{"MiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabitPerSecond, new string[]{"Mbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabitPerSecond, new string[]{"Mbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabitPerSecond, new string[]{"Mbit/s", "Mbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabytePerSecond, new string[]{"MB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibitPerSecond, new string[]{"Pibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibitPerSecond, new string[]{"Pibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibitPerSecond, new string[]{"Pibit/s", "Pibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibytePerSecond, new string[]{"PiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabitPerSecond, new string[]{"Pbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabitPerSecond, new string[]{"Pbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabitPerSecond, new string[]{"Pbit/s", "Pbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabytePerSecond, new string[]{"PB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibitPerSecond, new string[]{"Tibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibitPerSecond, new string[]{"Tibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibitPerSecond, new string[]{"Tibit/s", "Tibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibytePerSecond, new string[]{"TiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabitPerSecond, new string[]{"Tbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabitPerSecond, new string[]{"Tbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabitPerSecond, new string[]{"Tbit/s", "Tbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabytePerSecond, new string[]{"TB/s"}),
("en-US", typeof(BrakeSpecificFuelConsumptionUnit), (int)BrakeSpecificFuelConsumptionUnit.GramPerKiloWattHour, new string[]{"g/kWh"}),
("en-US", typeof(BrakeSpecificFuelConsumptionUnit), (int)BrakeSpecificFuelConsumptionUnit.KilogramPerJoule, new string[]{"kg/J"}),
@@ -226,37 +211,16 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Day, new string[]{"д"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Hour, new string[]{"h", "hr", "hrs", "hour", "hours"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Hour, new string[]{"ч"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µsec"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µsecs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µsecond"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µseconds"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мкс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мксек"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мкс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мксек"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"ms"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"msec"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"msecs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"msecond"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"mseconds"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мсек"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мсек"}),
+ ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µs", "µsec", "µsecs", "µsecond", "µseconds"}),
+ ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мкс", "мксек"}),
+ ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"ms", "msec", "msecs", "msecond", "mseconds"}),
+ ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мс", "мсек"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Minute, new string[]{"m", "min", "minute", "minutes"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Minute, new string[]{"мин"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Month30, new string[]{"mo", "month", "months"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Month30, new string[]{"месяц"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"ns"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nsec"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nsecs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nsecond"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nseconds"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нсек"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нсек"}),
+ ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"ns", "nsec", "nsecs", "nsecond", "nseconds"}),
+ ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нс", "нсек"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Second, new string[]{"s", "sec", "secs", "second", "seconds"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Second, new string[]{"с", "сек"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Week, new string[]{"wk", "week", "weeks"}),
@@ -592,18 +556,14 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(MassUnit), (int)MassUnit.Hectogram, new string[]{"гг"}),
("en-US", typeof(MassUnit), (int)MassUnit.Kilogram, new string[]{"kg"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Kilogram, new string[]{"кг"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klb"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klbs"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klbm"}),
+ ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klb", "klbs", "klbm"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"kфунт"}),
("en-US", typeof(MassUnit), (int)MassUnit.Kilotonne, new string[]{"kt"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Kilotonne, new string[]{"кт"}),
("en-US", typeof(MassUnit), (int)MassUnit.LongHundredweight, new string[]{"cwt"}),
("en-US", typeof(MassUnit), (int)MassUnit.LongTon, new string[]{"long tn"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.LongTon, new string[]{"тонна большая"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlb"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlbs"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlbm"}),
+ ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlb", "Mlbs", "Mlbm"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mфунт"}),
("en-US", typeof(MassUnit), (int)MassUnit.Megatonne, new string[]{"Mt"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Megatonne, new string[]{"Мт"}),
@@ -760,20 +720,14 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(MolarEntropyUnit), (int)MolarEntropyUnit.JoulePerMoleKelvin, new string[]{"J/(mol*K)"}),
("en-US", typeof(MolarEntropyUnit), (int)MolarEntropyUnit.KilojoulePerMoleKelvin, new string[]{"kJ/(mol*K)"}),
("en-US", typeof(MolarEntropyUnit), (int)MolarEntropyUnit.MegajoulePerMoleKelvin, new string[]{"MJ/(mol*K)"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.CentimolesPerLiter, new string[]{"cmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.CentimolesPerLiter, new string[]{"cM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.DecimolesPerLiter, new string[]{"dmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.DecimolesPerLiter, new string[]{"dM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MicromolesPerLiter, new string[]{"µmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MicromolesPerLiter, new string[]{"µM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MillimolesPerLiter, new string[]{"mmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MillimolesPerLiter, new string[]{"mM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.CentimolesPerLiter, new string[]{"cmol/L", "cM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.DecimolesPerLiter, new string[]{"dmol/L", "dM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MicromolesPerLiter, new string[]{"µmol/L", "µM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MillimolesPerLiter, new string[]{"mmol/L", "mM"}),
("en-US", typeof(MolarityUnit), (int)MolarityUnit.MolesPerCubicMeter, new string[]{"mol/m³"}),
("en-US", typeof(MolarityUnit), (int)MolarityUnit.MolesPerLiter, new string[]{"mol/L", "M"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.NanomolesPerLiter, new string[]{"nmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.NanomolesPerLiter, new string[]{"nM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.PicomolesPerLiter, new string[]{"pmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.PicomolesPerLiter, new string[]{"pM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.NanomolesPerLiter, new string[]{"nmol/L", "nM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.PicomolesPerLiter, new string[]{"pmol/L", "pM"}),
("en-US", typeof(MolarMassUnit), (int)MolarMassUnit.CentigramPerMole, new string[]{"cg/mol"}),
("ru-RU", typeof(MolarMassUnit), (int)MolarMassUnit.CentigramPerMole, new string[]{"сг/моль"}),
("en-US", typeof(MolarMassUnit), (int)MolarMassUnit.DecagramPerMole, new string[]{"dag/mol"}),
@@ -902,7 +856,6 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(PressureUnit), (int)PressureUnit.Kilopascal, new string[]{"кПа"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.KilopoundForcePerSquareFoot, new string[]{"kipf/ft²"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.KilopoundForcePerSquareInch, new string[]{"kipf/in²"}),
- ("en-US", typeof(PressureUnit), (int)PressureUnit.KilopoundForcePerSquareInch, new string[]{"kipf/in²"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.Megabar, new string[]{"Mbar"}),
("ru-RU", typeof(PressureUnit), (int)PressureUnit.Megabar, new string[]{"Mбар"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.MeganewtonPerSquareMeter, new string[]{"MN/m²"}),
@@ -974,18 +927,15 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.DegreePerMinute, new string[]{"°/min", "deg/min"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.DegreePerSecond, new string[]{"°/s", "deg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.DegreePerSecond, new string[]{"°/с"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µ°/s"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µdeg/s"}),
+ ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µ°/s", "µdeg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µ°/с"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicroradianPerSecond, new string[]{"µrad/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicroradianPerSecond, new string[]{"µрад/с"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"m°/s"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"mdeg/s"}),
+ ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"m°/s", "mdeg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"m°/с"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MilliradianPerSecond, new string[]{"mrad/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MilliradianPerSecond, new string[]{"mрад/с"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"n°/s"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"ndeg/s"}),
+ ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"n°/s", "ndeg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"n°/с"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanoradianPerSecond, new string[]{"nrad/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanoradianPerSecond, new string[]{"nрад/с"}),
@@ -995,15 +945,11 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.RevolutionPerMinute, new string[]{"об/мин"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.RevolutionPerSecond, new string[]{"r/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.RevolutionPerSecond, new string[]{"об/с"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.KilonewtonMeterPerRadian, new string[]{"kN·m/rad"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.KilonewtonMeterPerRadian, new string[]{"kNm/rad"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.MeganewtonMeterPerRadian, new string[]{"MN·m/rad"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.MeganewtonMeterPerRadian, new string[]{"MNm/rad"}),
+ ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.KilonewtonMeterPerRadian, new string[]{"kN·m/rad", "kNm/rad"}),
+ ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.MeganewtonMeterPerRadian, new string[]{"MN·m/rad", "MNm/rad"}),
("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.NewtonMeterPerRadian, new string[]{"N·m/rad", "Nm/rad"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.KilonewtonMeterPerRadianPerMeter, new string[]{"kN·m/rad/m"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.KilonewtonMeterPerRadianPerMeter, new string[]{"kNm/rad/m"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.MeganewtonMeterPerRadianPerMeter, new string[]{"MN·m/rad/m"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.MeganewtonMeterPerRadianPerMeter, new string[]{"MNm/rad/m"}),
+ ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.KilonewtonMeterPerRadianPerMeter, new string[]{"kN·m/rad/m", "kNm/rad/m"}),
+ ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.MeganewtonMeterPerRadianPerMeter, new string[]{"MN·m/rad/m", "MNm/rad/m"}),
("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.NewtonMeterPerRadianPerMeter, new string[]{"N·m/rad/m", "Nm/rad/m"}),
("en-US", typeof(SolidAngleUnit), (int)SolidAngleUnit.Steradian, new string[]{"sr"}),
("en-US", typeof(SpecificEnergyUnit), (int)SpecificEnergyUnit.BtuPerPound, new string[]{"btu/lb"}),
@@ -1247,9 +1193,7 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.AcreFootPerHour, new string[]{"af/h"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.AcreFootPerMinute, new string[]{"af/m"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.AcreFootPerSecond, new string[]{"af/s"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cl/day", "cL/d", "cLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerMinute, new string[]{"cLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicDecimeterPerMinute, new string[]{"dm³/min"}),
("ru-RU", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicDecimeterPerMinute, new string[]{"дм³/мин"}),
@@ -1268,13 +1212,9 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicYardPerHour, new string[]{"yd³/h"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicYardPerMinute, new string[]{"yd³/min"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicYardPerSecond, new string[]{"yd³/s"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dl/day", "dL/d", "dLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerMinute, new string[]{"dLPM"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kl/day", "kL/d", "kLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerMinute, new string[]{"kLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KilousGallonPerMinute, new string[]{"kgal (U.S.)/min", "KGPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerDay, new string[]{"l/day", "L/d", "LPD"}),
@@ -1282,22 +1222,14 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerHour, new string[]{"л/ч"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerMinute, new string[]{"LPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerSecond, new string[]{"LPS"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"Ml/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"ML/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"MLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"Ml/day", "ML/d", "MLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaukGallonPerSecond, new string[]{"Mgal (imp.)/s"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µl/day", "µL/d", "µLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerMinute, new string[]{"µLPM"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"ml/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"mL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"mLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"ml/day", "mL/d", "mLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerMinute, new string[]{"mLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MillionUsGallonsPerDay, new string[]{"MGD"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nl/day", "nL/d", "nLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerMinute, new string[]{"nLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.OilBarrelPerDay, new string[]{"bbl/d", "BOPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.OilBarrelPerHour, new string[]{"bbl/hr", "bph"}),
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/GenerateUnits.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/GenerateUnits.ps1
deleted file mode 100644
index 7147eeabc5..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/GenerateUnits.ps1
+++ /dev/null
@@ -1,343 +0,0 @@
-using module ".\Types.psm1"
-
-#Requires -Version 5.1
-
-# Set Write-Output used by Include- files to UTF8 encoding to fix copyright character
-[Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
-$OutputEncoding = [Text.UTF8Encoding]::UTF8
-
-# DaddyCool => daddyCool
-function ToCamelCase($str)
-{
- return $str.Substring(0,1).ToLowerInvariant() + $str.Substring(1)
-}
-
-function ValueOrDefault($value, $defaultValue){
- if ($value -ne $null) { $value } else { $defaultValue }
-}
-
-function GenerateQuantity([Quantity]$quantity, $outDir)
-{
- $outFileName = "$outDir/$($quantity.Name).WindowsRuntimeComponent.g.cs"
- GenerateQuantitySourceCode $quantity | Out-File -Encoding "UTF8" $outFileName | Out-Null
- if (!$?) { exit 1 }
- Write-Host -NoNewline "quantity(OK) "
-}
-
-function GenerateUnitTestBaseClass([Quantity]$quantity, $outDir)
-{
- $outFileName = "$outDir/$($quantity.Name)TestsBase.g.cs"
- GenerateUnitTestBaseClassSourceCode $quantity | Out-File -Encoding "UTF8" $outFileName | Out-Null
- if (!$?) {
- exit 1
- }
- Write-Host -NoNewline "test base(OK) "
-}
-
-function GenerateUnitTestClassIfNotExists([Quantity]$quantity, $outDir)
-{
- Write-Host -NoNewline "test stub"
- $outFileName = "$outDir/$($quantity.Name)Tests.cs"
- if (Test-Path $outFileName)
- {
- Write-Host -NoNewline "(skip) "
- return
- }
- else
- {
- GenerateUnitTestPlaceholderSourceCode $quantity | Out-File -Encoding "UTF8" $outFileName | Out-Null
- if (!$?) {
- exit 1
- }
- Write-Host -NoNewline "(OK) "
- }
-}
-
-function GenerateUnitType([Quantity]$quantity, $outDir)
-{
- $outFileName = "$outDir/$($quantity.Name)Unit.g.cs"
-
- GenerateUnitTypeSourceCode $quantity | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- exit 1
- }
- Write-Host -NoNewline "unit(OK) "
-}
-
-function GenerateUnitSystemDefault($quantities, $outDir)
-{
- Write-Host -NoNewline "UnitAbbreviationsCache.g.cs: "
- $outFileName = "$outDir/UnitAbbreviationsCache.g.cs"
-
- GenerateUnitSystemDefaultSourceCode $quantities | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- Write-Host "(error) "
- exit 1
- }
- Write-Host "(OK) "
-}
-
-function GenerateQuantityType($quantities, $outDir)
-{
- Write-Host -NoNewline "QuantityType.g.cs: "
- $outFileName = "$outDir/QuantityType.g.cs"
-
- GenerateQuantityTypeSourceCode $quantities | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- Write-Host "(error) "
- exit 1
- }
- Write-Host "(OK) "
-}
-
-function GenerateStaticQuantity($quantities, $outDir)
-{
- Write-Host -NoNewline "Quantity.g.cs: "
- $outFileName = "$outDir/Quantity.g.cs"
-
- GenerateStaticQuantitySourceCode $quantities | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- Write-Host "(error) "
- exit 1
- }
- Write-Host "(OK) "
-}
-
-function EnsureDirExists([String] $dirPath) {
- New-Item -ItemType Directory -Force -Path $dirPath | Out-Null
- if (!$?) {
- exit 1
- }
-}
-
-function Set-ConversionFunctions
-{
- param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $quantity)
- PROCESS {
- foreach ($u in $quantity.Units) {
-
- # Use decimal for internal calculations if base type is not double, such as for long or int.
- if ($quantity.BaseType -eq "decimal") {
- $u.FromUnitToBaseFunc = $u.FromUnitToBaseFunc -replace "d", "m"
- $u.FromBaseToUnitFunc = $u.FromBaseToUnitFunc -replace "d", "m"
- }
-
- # Convert to/from double for other base types
- $u.FromUnitToBaseFunc = "$($u.FromUnitToBaseFunc)"
- $u.FromBaseToUnitFunc = "$($u.FromBaseToUnitFunc)"
- }
- return $quantity
- }
-}
-
-function Add-PrefixUnits {
- param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $quantity)
- PROCESS {
- $prefixUnits = @()
-
- foreach ($unit in $quantity.Units)
- {
- foreach ($localization in $unit.Localization){
- if($localization.AbbreviationsWithPrefixes.Count -gt 0){
- if($unit.Prefixes.Count -ne $localization.AbbreviationsWithPrefixes.Count){
- Write-Error "The prefix count ($($unit.Prefixes.Count)) does not match the abbreviations with prefixes count ($($localization.AbbreviationsWithPrefixes.Count)) for $($quantity.Name).$($unit.SingularName)" -ErrorAction Stop
- }
- }
- }
-
- $prefixIndex = 0
- foreach ($prefix in $unit.Prefixes)
- {
- $prefixInfo = switch ($prefix)
- {
- "Kilo" { "k", "1e3d"; break; }
- "Hecto" { "h", "1e2d"; break; }
- "Deca" { "da", "1e1d"; break; }
- "Deci" { "d", "1e-1d"; break; }
- "Centi" { "c", "1e-2d"; break; }
- "Milli" { "m", "1e-3d"; break; }
- "Micro" { "µ", "1e-6d"; break; }
- "Nano" { "n", "1e-9d"; break; }
-
- # Optimization, move less frequently used prefixes to the end
- "Pico" { "p", "1e-12d"; break; }
- "Femto" { "f", "1e-15d"; break; }
- "Atto" { "a", "1e-18d"; break; }
- "Zepto" { "z", "1e-21d"; break; }
- "Yocto" { "y", "1e-24d"; break; }
-
- "Yotta" { "Y", "1e24d"; break; }
- "Zetta" { "Z", "1e21d"; break; }
- "Exa" { "E", "1e18d"; break; }
- "Peta" { "P", "1e15d"; break; }
- "Tera" { "T", "1e12d"; break; }
- "Giga" { "G", "1e9d"; break; }
- "Mega" { "M", "1e6d"; break; }
-
- # Binary prefixes
- "Kibi" { "Ki", "1024d"; break; }
- "Mebi" { "Mi", "(1024d * 1024)"; break; }
- "Gibi" { "Gi", "(1024d * 1024 * 1024)"; break; }
- "Tebi" { "Ti", "(1024d * 1024 * 1024 * 1024)"; break; }
- "Pebi" { "Pi", "(1024d * 1024 * 1024 * 1024 * 1024)"; break; }
- "Exbi" { "Ei", "(1024d * 1024 * 1024 * 1024 * 1024 * 1024)"; break; }
- }
-
- $prefixAbbreviation = $prefixInfo[0]
- $prefixFactor = $prefixInfo[1]
-
- $prefixUnit = New-Object PsObject -Property @{
- SingularName=$prefix + $(ToCamelCase $unit.SingularName)
- PluralName=$prefix + $(ToCamelCase $unit.PluralName)
- FromUnitToBaseFunc="("+$unit.FromUnitToBaseFunc+") * $prefixFactor"
- FromBaseToUnitFunc="("+$unit.FromBaseToUnitFunc+") / $prefixFactor"
-
- Localization=$unit.Localization | % {
- foreach ($abbrSyno in $_.Abbreviations) {
- $abbrev = $prefixAbbreviation + $abbrSyno
- if ($_.AbbreviationsWithPrefixes) {
- if($_.AbbreviationsWithPrefixes[$prefixIndex] -isnot [System.String]){
- foreach($synoWithPrefix in $_.AbbreviationsWithPrefixes[$prefixIndex]){
- New-Object PsObject -Property @{
- Culture=$_.Culture
- Abbreviations= $synoWithPrefix
- }
- }
- continue
- }
- else{
- $abbrev = $_.AbbreviationsWithPrefixes[$prefixIndex]
- }
- }
- New-Object PsObject -Property @{
- Culture=$_.Culture
- Abbreviations= $abbrev
- }
- }
- }
- }
-
- # Append prefix unit
- $prefixUnits += $prefixUnit
- $prefixIndex++;
- } # foreach prefixes
- } # foreach units
-
- $quantity.Units += $prefixUnits
- return $quantity
- }
-}
-
-function Set-UnitsOrderedByName {
- param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $quantity)
- PROCESS {
- $quantity.Units = ($quantity.Units | sort SingularName)
- return $quantity
- }
-}
-
-function Add-InheritedUnits([Quantity]$quantity, $quantities) {
-
- foreach ($inheritFromQuantityName in $quantity.InheritUnitsFrom) {
- $inheritFromQuantity = $quantities | Where { $_.Name -eq $inheritFromQuantityName } | Select -First 1
- $quantity.Units += $inheritFromQuantity.Units
-
- Write-Host -NoNewline "(inherit $inheritFromQuantityName) "
- }
-}
-
-# Load external generator functions with same name as file
-. "$PSScriptRoot/Include-GenerateTemplates.ps1"
-. "$PSScriptRoot/Include-GenerateUnitSystemDefaultSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateQuantityTypeSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateStaticQuantitySourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateQuantitySourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateUnitTypeSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateUnitTestBaseClassSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateUnitTestPlaceholderSourceCode.ps1"
-
-EnsureDirExists ($quantityDir = "$PSScriptRoot/../GeneratedCode/Quantities")
-EnsureDirExists ($unitEnumDir = "$PSScriptRoot/../GeneratedCode/Units")
-EnsureDirExists ($unitSystemDir = "$PSScriptRoot/../GeneratedCode")
-EnsureDirExists ($testsDir = "$PSScriptRoot/../../UnitsNet.Tests/GeneratedCode")
-EnsureDirExists ($testsCustomCodeDir = "$PSScriptRoot/../../UnitsNet.Tests/CustomCode")
-
-$templatesDir = "$PSScriptRoot/../../Common/UnitDefinitions"
-$pad = 25
-
-# Parse unit definitions from .json files
-# TODO Find a way to automap from JSON into Quantity type
-$quantities = Get-ChildItem -Path $templatesDir -filter "*.json" `
- | %{(Get-Content $_.FullName -Encoding "UTF8" | Out-String)} `
- | ConvertFrom-Json `
- | %{
- # $_ | fl | out-string | write-host -foreground blue
- # New-Object -TypeName Quantity -Verbose -Property @{
- [Quantity]@{
- Name = $_.Name
- XmlDocSummary = $_.XmlDoc
- XmlDocRemarks = $_.XmlDocRemarks
- BaseUnit = $_.BaseUnit
- BaseType = ValueOrDefault $_.BaseType "double"
- BaseDimensions = @{
- Length = ValueOrDefault $_.BaseDimensions.L 0
- Mass = ValueOrDefault $_.BaseDimensions.M 0
- Time = ValueOrDefault $_.BaseDimensions.T 0
- ElectricCurrent = ValueOrDefault $_.BaseDimensions.I 0
- Temperature = ValueOrDefault $_.BaseDimensions.Θ 0
- AmountOfSubstance = ValueOrDefault $_.BaseDimensions.N 0
- LuminousIntensity = ValueOrDefault $_.BaseDimensions.J 0
- }
- GenerateArithmetic = ValueOrDefault $_.GenerateArithmetic $true
- Logarithmic = ValueOrDefault $_.Logarithmic $false
- LogarithmicScalingFactor = ValueOrDefault $_.LogarithmicScalingFactor 1
- Units = $_.Units | %{
- # $_ | fl | out-string | Write-Host -ForegroundColor blue
- [Unit]@{
- SingularName = $_.SingularName
- PluralName = $_.PluralName
- XmlDocSummary = $_.XmlDocSummary
- XmlDocRemarks = $_.XmlDocRemarks
- FromUnitToBaseFunc = $_.FromUnitToBaseFunc
- FromBaseToUnitFunc = $_.FromBaseToUnitFunc
- Prefixes = [string[]](ValueOrDefault $_.Prefixes @())
- Localization = $_.Localization | %{
- # $_ | fl | out-string | Write-Host -ForegroundColor blue
- [Localization]@{
- Culture = $_.Culture
- Abbreviations = $_.Abbreviations
- AbbreviationsWithPrefixes = $_.AbbreviationsWithPrefixes
- }
- }
- }
- }
- }
- } `
- | Add-PrefixUnits `
- | Set-ConversionFunctions `
- | Set-UnitsOrderedByName
-
-foreach ($quantity in $quantities) {
- Write-Host -NoNewline "$($quantity.Name):".PadRight($pad)
-
- Add-InheritedUnits $quantity $quantities
-
- GenerateQuantity $quantity $quantityDir
- GenerateUnitType $quantity $unitEnumDir
- GenerateUnitTestBaseClass $quantity $testsDir
- GenerateUnitTestClassIfNotExists $quantity $testsCustomCodeDir
-
- Write-Host ""
-}
-
-Write-Host ""
-GenerateUnitSystemDefault $quantities $unitSystemDir
-GenerateQuantityType $quantities $unitSystemDir
-GenerateStaticQuantity $quantities $unitSystemDir
-
-$unitCount = ($quantities | %{$_.Units.Count} | Measure -Sum).Sum
-
-Write-Host "`n`n"
-Write-Host -Foreground Yellow "Summary: $unitCount units in $($quantities.Count) quantities".PadRight($pad)
-Write-Host "`n`n"
-exit 0
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateQuantitySourceCode.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateQuantitySourceCode.ps1
deleted file mode 100644
index f4d5fdff40..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateQuantitySourceCode.ps1
+++ /dev/null
@@ -1,727 +0,0 @@
-using module ".\Types.psm1"
-
-function GenerateQuantitySourceCode([Quantity]$quantity)
-{
- $quantityName = $quantity.Name;
- $units = $quantity.Units;
- $valueType = $quantity.BaseType;
- [Unit]$baseUnit = $units | where { $_.SingularName -eq $quantity.BaseUnit } | Select-Object -First 1
- $baseUnitSingularName = $baseUnit.SingularName
- $unitEnumName = "$quantityName" + "Unit"
-
- $baseDimensions = $quantity.BaseDimensions;
- $isDimensionless = $null -eq $baseDimensions -or ( $baseDimensions.Length -eq 0 -and $baseDimensions.Mass -eq 0 -and $baseDimensions.Time -eq 0 -and $baseDimensions.ElectricCurrent -eq 0 -and $baseDimensions.Temperature -eq 0 -and $baseDimensions.AmountOfSubstance -eq 0 -and $baseDimensions.LuminousIntensity -eq 0 )
-
- [GeneratorArgs]$genArgs = New-Object GeneratorArgs -Property @{
- Quantity = $quantity;
- BaseUnit = $baseUnit;
- UnitEnumName = $unitEnumName;
- }
- # $genArgs | fl | out-string | write-host -foreground yellow
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using System.Globalization;
-using System.Linq;
-using JetBrains.Annotations;
-using UnitsNet.Units;
-using UnitsNet.InternalHelpers;
-
-// ReSharper disable once CheckNamespace
-
-namespace UnitsNet
-{
-"@;
- $obsoleteAttribute = GetObsoleteAttribute($quantity);
- if ($obsoleteAttribute)
- {
- $obsoleteAttribute = "`r`n " + $obsoleteAttribute; # apply padding to conformance with code format in this section
- }@"
- ///
- /// $($quantity.XmlDocSummary)
- ///
-"@; if ($quantity.XmlDocRemarks) {@"
- ///
- /// $($quantity.XmlDocRemarks)
- ///
-"@; }@"
- // Windows Runtime Component has constraints on public types: https://msdn.microsoft.com/en-us/library/br230301.aspx#Declaring types in Windows Runtime Components
- // Public structures can't have any members other than public fields, and those fields must be value types or strings.
- // Public classes must be sealed (NotInheritable in Visual Basic). If your programming model requires polymorphism, you can create a public interface and implement that interface on the classes that must be polymorphic.
- public sealed partial class $quantityName : IQuantity
- {
- ///
- /// The numeric value this quantity was constructed with.
- ///
- private readonly $valueType _value;
-
- ///
- /// The unit this quantity was constructed with.
- ///
- private readonly $($unitEnumName)? _unit;
-
- static $quantityName()
- {
-"@; if($isDimensionless) {@"
- BaseDimensions = BaseDimensions.Dimensionless;
-"@; } else {@"
- BaseDimensions = new BaseDimensions($($baseDimensions.Length), $($baseDimensions.Mass), $($baseDimensions.Time), $($baseDimensions.ElectricCurrent), $($baseDimensions.Temperature), $($baseDimensions.AmountOfSubstance), $($baseDimensions.LuminousIntensity));
-"@; }@"
- Info = new QuantityInfo(QuantityType.$quantityName, Units.Cast().ToArray(), BaseUnit, Zero, BaseDimensions);
- }
-
- ///
- /// Creates the quantity with a value of 0 in the base unit $baseUnitSingularName.
- ///
- ///
- /// Windows Runtime Component requires a default constructor.
- ///
- public $quantityName()
- {
- _value = 0;
- _unit = BaseUnit;
- }
-
- ///
- /// Creates the quantity with the given numeric value and unit.
- ///
- /// The numeric value to contruct this quantity with.
- /// The unit representation to contruct this quantity with.
- /// Value parameter cannot be named 'value' due to constraint when targeting Windows Runtime Component.
- /// If value is NaN or Infinity.
- private $quantityName($valueType numericValue, $unitEnumName unit)
- {
- if(unit == $unitEnumName.Undefined)
- throw new ArgumentException("The quantity can not be created with an undefined unit.", nameof(unit));
-
-"@; if ($quantity.BaseType -eq "double") {@"
- _value = Guard.EnsureValidNumber(numericValue, nameof(numericValue));
-"@; } else {@"
- _value = numericValue;
-"@; }@"
- _unit = unit;
- }
-"@;
- GenerateStaticProperties $genArgs
- GenerateProperties $genArgs
- GenerateConversionProperties $genArgs
- GenerateStaticMethods $genArgs
- GenerateStaticFactoryMethods $genArgs
- GenerateStaticParseMethods $genArgs
- GenerateEqualityAndComparison $genArgs
- GenerateConversionMethods $genArgs
-@"
-
- #region ToString Methods
-
- ///
- /// Get default string representation of value and unit.
- ///
- /// String representation.
- public override string ToString()
- {
- return ToString(null);
- }
-
- ///
- /// Get string representation of value and unit. Using two significant digits after radix.
- ///
- /// String representation.
- /// Name of culture (ex: "en-US") to use for localization and number formatting. Defaults to if null.
- public string ToString([CanBeNull] string cultureName)
- {
- var provider = cultureName;
- return ToString(provider, 2);
- }
-
- ///
- /// Get string representation of value and unit.
- ///
- /// The number of significant digits after the radix point.
- /// String representation.
- /// Name of culture (ex: "en-US") to use for localization and number formatting. Defaults to if null.
- public string ToString(string cultureName, int significantDigitsAfterRadix)
- {
- var provider = cultureName;
- var value = Convert.ToDouble(Value);
- var format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix);
- return ToString(provider, format);
- }
-
- ///
- /// Get string representation of value and unit.
- ///
- /// String format to use. Default: "{0:0.##} {1} for value and unit abbreviation respectively."
- /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1.
- /// String representation.
- /// Name of culture (ex: "en-US") to use for localization and number formatting. Defaults to if null.
- public string ToString([CanBeNull] string cultureName, [NotNull] string format, [NotNull] params object[] args)
- {
- var provider = GetFormatProviderFromCultureName(cultureName);
- if (format == null) throw new ArgumentNullException(nameof(format));
- if (args == null) throw new ArgumentNullException(nameof(args));
-
- provider = provider ?? GlobalConfiguration.DefaultCulture;
-
- var value = Convert.ToDouble(Value);
- var formatArgs = UnitFormatter.GetFormatArgs(Unit, value, provider, args);
- return string.Format(provider, format, formatArgs);
- }
-
- #endregion
-
- private static IFormatProvider GetFormatProviderFromCultureName([CanBeNull] string cultureName)
- {
- return cultureName != null ? new CultureInfo(cultureName) : (IFormatProvider)null;
- }
- }
-}
-"@;
-}
-
-function GenerateStaticProperties([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $baseUnitSingularName = $genArgs.BaseUnit.SingularName
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Static Properties
-
- ///
- /// Information about the quantity type, such as unit values and names.
- ///
- internal static QuantityInfo Info { get; }
-
- ///
- /// The of this quantity.
- ///
- public static BaseDimensions BaseDimensions { get; }
-
- ///
- /// The base unit of $quantityName, which is $baseUnitSingularName. All conversions go via this value.
- ///
- public static $unitEnumName BaseUnit { get; } = $unitEnumName.$baseUnitSingularName;
-
- ///
- /// Represents the largest possible value of $quantityName
- ///
- public static $quantityName MaxValue { get; } = new $quantityName($valueType.MaxValue, BaseUnit);
-
- ///
- /// Represents the smallest possible value of $quantityName
- ///
- public static $quantityName MinValue { get; } = new $quantityName($valueType.MinValue, BaseUnit);
-
- ///
- /// The of this quantity.
- ///
- public static QuantityType QuantityType { get; } = QuantityType.$quantityName;
-
- ///
- /// All units of measurement for the $quantityName quantity.
- ///
- public static $unitEnumName[] Units { get; } = Enum.GetValues(typeof($unitEnumName)).Cast<$unitEnumName>().Except(new $unitEnumName[]{ $unitEnumName.Undefined }).ToArray();
-
- ///
- /// Gets an instance of this quantity with a value of 0 in the base unit $baseUnitSingularName.
- ///
- public static $quantityName Zero { get; } = new $quantityName(0, BaseUnit);
-
- #endregion
-"@;
-}
-
-function GenerateProperties([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
-@"
-
- #region Properties
-
- ///
- /// The numeric value this quantity was constructed with.
- ///
- public double Value => Convert.ToDouble(_value);
-
- ///
- object IQuantity.Unit => Unit;
-
- ///
- /// The unit this quantity was constructed with -or- if default ctor was used.
- ///
- public $unitEnumName Unit => _unit.GetValueOrDefault(BaseUnit);
-
- internal QuantityInfo QuantityInfo => Info;
-
- ///
- /// The of this quantity.
- ///
- public QuantityType Type => $quantityName.QuantityType;
-
- ///
- /// The of this quantity.
- ///
- public BaseDimensions Dimensions => $quantityName.BaseDimensions;
-
- #endregion
-"@;
-}
-
-function GenerateConversionProperties([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $units = $genArgs.Quantity.Units
-@"
-
- #region Conversion Properties
-"@;
- foreach ($unit in $units) {
- $propertyName = $unit.PluralName;
- $obsoleteAttribute = GetObsoleteAttribute($unit);
- if ($obsoleteAttribute)
- {
- $obsoleteAttribute = "`r`n " + $obsoleteAttribute; # apply padding to conformance with code format in this page
- }
-@"
-
- ///
- /// Get $quantityName in $propertyName.
- /// $($obsoleteAttribute)
- public double $propertyName => As($unitEnumName.$($unit.SingularName));
-"@; }
-@"
-
- #endregion
-"@;
-}
-
-function GenerateStaticMethods([GeneratorArgs]$genArgs)
-{
- $unitEnumName = $genArgs.UnitEnumName
-@"
-
- #region Static Methods
-
- ///
- /// Get unit abbreviation string.
- ///
- /// Unit to get abbreviation for.
- /// Unit abbreviation string.
- public static string GetAbbreviation($unitEnumName unit)
- {
- return GetAbbreviation(unit, null);
- }
-
- ///
- /// Get unit abbreviation string.
- ///
- /// Unit to get abbreviation for.
- /// Unit abbreviation string.
- /// Name of culture (ex: "en-US") to use when parsing number and unit. Defaults to if null.
- public static string GetAbbreviation($unitEnumName unit, [CanBeNull] string cultureName)
- {
- IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
- return UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit, provider);
- }
-
- #endregion
-"@;
-}
-
-function GenerateStaticFactoryMethods([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $units = $genArgs.Quantity.Units
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Static Factory Methods
-
-"@; foreach ($unit in $units) {
- $valueParamName = $unit.PluralName.ToLowerInvariant();
- $obsoleteAttribute = GetObsoleteAttribute($unit);
- if ($obsoleteAttribute)
- {
- $obsoleteAttribute = "`r`n " + $obsoleteAttribute; # apply padding to conformance with code format in this page
- }
- @"
- ///
- /// Get $quantityName from $($unit.PluralName).
- /// $($obsoleteAttribute)
- /// If value is NaN or Infinity.
- [Windows.Foundation.Metadata.DefaultOverload]
- public static $quantityName From$($unit.PluralName)(double $valueParamName)
- {
- $valueType value = ($valueType) $valueParamName;
- return new $quantityName(value, $unitEnumName.$($unit.SingularName));
- }
-"@; }@"
-
- ///
- /// Dynamically convert from value and unit enum to .
- ///
- /// Value to convert from.
- /// Unit to convert from.
- /// $quantityName unit value.
- // Fix name conflict with parameter "value"
- [return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName("returnValue")]
- public static $quantityName From(double value, $unitEnumName fromUnit)
- {
- return new $quantityName(($valueType)value, fromUnit);
- }
-
- #endregion
-"@;
-
-}
-
-function GenerateStaticParseMethods([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
-@"
-
- #region Static Parse Methods
-
- ///
- /// Parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- ///
- /// Expected string to have one or two pairs of quantity and unit in the format
- /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in"
- ///
- ///
- /// More than one unit is represented by the specified unit abbreviation.
- /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of
- /// , and .
- ///
- ///
- /// If anything else goes wrong, typically due to a bug or unhandled case.
- /// We wrap exceptions in to allow you to distinguish
- /// Units.NET exceptions from other exceptions.
- ///
- public static $quantityName Parse(string str)
- {
- return Parse(str, null);
- }
-
- ///
- /// Parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- ///
- /// Expected string to have one or two pairs of quantity and unit in the format
- /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in"
- ///
- ///
- /// More than one unit is represented by the specified unit abbreviation.
- /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of
- /// , and .
- ///
- ///
- /// If anything else goes wrong, typically due to a bug or unhandled case.
- /// We wrap exceptions in to allow you to distinguish
- /// Units.NET exceptions from other exceptions.
- ///
- /// Name of culture (ex: "en-US") to use when parsing number and unit. Defaults to if null.
- public static $quantityName Parse(string str, [CanBeNull] string cultureName)
- {
- IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
- return QuantityParser.Default.Parse<$quantityName, $unitEnumName>(
- str,
- provider,
- From);
- }
-
- ///
- /// Try to parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- /// Resulting unit quantity if successful.
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- public static bool TryParse([CanBeNull] string str, out $quantityName result)
- {
- return TryParse(str, null, out result);
- }
-
- ///
- /// Try to parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- /// Resulting unit quantity if successful.
- /// True if successful, otherwise false.
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- /// Name of culture (ex: "en-US") to use when parsing number and unit. Defaults to if null.
- public static bool TryParse([CanBeNull] string str, [CanBeNull] string cultureName, out $quantityName result)
- {
- IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
- return QuantityParser.Default.TryParse<$quantityName, $unitEnumName>(
- str,
- provider,
- From,
- out result);
- }
-
- ///
- /// Parse a unit string.
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.ParseUnit("m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- /// Error parsing string.
- public static $unitEnumName ParseUnit(string str)
- {
- return ParseUnit(str, null);
- }
-
- ///
- /// Parse a unit string.
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.ParseUnit("m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- /// Error parsing string.
- /// Name of culture (ex: "en-US") to use when parsing number and unit. Defaults to if null.
- public static $unitEnumName ParseUnit(string str, [CanBeNull] string cultureName)
- {
- IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
- return UnitParser.Default.Parse<$unitEnumName>(str, provider);
- }
-
- public static bool TryParseUnit(string str, out $unitEnumName unit)
- {
- return TryParseUnit(str, null, out unit);
- }
-
- ///
- /// Parse a unit string.
- ///
- /// String to parse. Typically in the form: {number} {unit}
- /// The parsed unit if successful.
- /// True if successful, otherwise false.
- ///
- /// Length.TryParseUnit("m", new CultureInfo("en-US"));
- ///
- /// Name of culture (ex: "en-US") to use when parsing number and unit. Defaults to if null.
- public static bool TryParseUnit(string str, [CanBeNull] string cultureName, out $unitEnumName unit)
- {
- IFormatProvider provider = GetFormatProviderFromCultureName(cultureName);
- return UnitParser.Default.TryParse<$unitEnumName>(str, provider, out unit);
- }
-
- #endregion
-"@;
-}
-
-function GenerateEqualityAndComparison([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
-@"
-
- #region Equality / IComparable
-
- public int CompareTo(object obj)
- {
- if(obj is null) throw new ArgumentNullException(nameof(obj));
- if(!(obj is $quantityName obj$quantityName)) throw new ArgumentException("Expected type $quantityName.", nameof(obj));
-
- return CompareTo(obj$quantityName);
- }
-
- // Windows Runtime Component does not allow public methods/ctors with same number of parameters: https://msdn.microsoft.com/en-us/library/br230301.aspx#Overloaded methods
- internal int CompareTo($quantityName other)
- {
- return _value.CompareTo(other.AsBaseNumericType(this.Unit));
- }
-
- [Windows.Foundation.Metadata.DefaultOverload]
- public override bool Equals(object obj)
- {
- if(obj is null || !(obj is $quantityName obj$quantityName))
- return false;
-
- return Equals(obj$quantityName);
- }
-
- public bool Equals($quantityName other)
- {
- return _value.Equals(other.AsBaseNumericType(this.Unit));
- }
-
- ///
- ///
- /// Compare equality to another $quantityName within the given absolute or relative tolerance.
- ///
- ///
- /// Relative tolerance is defined as the maximum allowable absolute difference between this quantity's value and
- /// as a percentage of this quantity's value. will be converted into
- /// this quantity's unit for comparison. A relative tolerance of 0.01 means the absolute difference must be within +/- 1% of
- /// this quantity's value to be considered equal.
- ///
- /// In this example, the two quantities will be equal if the value of b is within +/- 1% of a (0.02m or 2cm).
- ///
- /// var a = Length.FromMeters(2.0);
- /// var b = Length.FromInches(50.0);
- /// a.Equals(b, 0.01, ComparisonType.Relative);
- ///
- ///
- ///
- ///
- /// Absolute tolerance is defined as the maximum allowable absolute difference between this quantity's value and
- /// as a fixed number in this quantity's unit. will be converted into
- /// this quantity's unit for comparison.
- ///
- /// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
- ///
- /// var a = Length.FromMeters(2.0);
- /// var b = Length.FromInches(50.0);
- /// a.Equals(b, 0.01, ComparisonType.Absolute);
- ///
- ///
- ///
- ///
- /// Note that it is advised against specifying zero difference, due to the nature
- /// of floating point operations and using System.Double internally.
- ///
- ///
- /// The other quantity to compare to.
- /// The absolute or relative tolerance value. Must be greater than or equal to 0.
- /// The comparison type: either relative or absolute.
- /// True if the absolute difference between the two values is not greater than the specified relative or absolute tolerance.
- public bool Equals($quantityName other, double tolerance, ComparisonType comparisonType)
- {
- if(tolerance < 0)
- throw new ArgumentOutOfRangeException("tolerance", "Tolerance must be greater than or equal to 0.");
-
- double thisValue = (double)this.Value;
- double otherValueInThisUnits = other.As(this.Unit);
-
- return UnitsNet.Comparison.Equals(thisValue, otherValueInThisUnits, tolerance, comparisonType);
- }
-
- ///
- /// Returns the hash code for this instance.
- ///
- /// A hash code for the current $quantityName.
- public override int GetHashCode()
- {
- return new { QuantityType, Value, Unit }.GetHashCode();
- }
-
- #endregion
-"@;
-}
-
-function GenerateConversionMethods([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Conversion Methods
-
- double IQuantity.As(object unit) => As(($unitEnumName)unit);
-
- ///
- /// Convert to the unit representation .
- ///
- /// Value converted to the specified unit.
- public double As($unitEnumName unit)
- {
- if(Unit == unit)
- return Convert.ToDouble(Value);
-
- var converted = AsBaseNumericType(unit);
- return Convert.ToDouble(converted);
- }
-
- ///
- /// Converts this $quantityName to another $quantityName with the unit representation .
- ///
- /// A $quantityName with the specified unit.
- public $quantityName ToUnit($unitEnumName unit)
- {
- var convertedValue = AsBaseNumericType(unit);
- return new $quantityName(convertedValue, unit);
- }
-
- ///
- /// Converts the current value + unit to the base unit.
- /// This is typically the first step in converting from one unit to another.
- ///
- /// The value in the base unit representation.
- private $valueType AsBaseUnit()
- {
- switch(Unit)
- {
-"@; foreach ($unit in $units) {
- $func = $unit.FromUnitToBaseFunc.Replace("x", "_value");@"
- case $unitEnumName.$($unit.SingularName): return $func;
-"@; }@"
- default:
- throw new NotImplementedException($"Can not convert {Unit} to base units.");
- }
- }
-
- private $valueType AsBaseNumericType($unitEnumName unit)
- {
- if(Unit == unit)
- return _value;
-
- var baseUnitValue = AsBaseUnit();
-
- switch(unit)
- {
-"@; foreach ($unit in $units) {
- $func = $unit.FromBaseToUnitFunc.Replace("x", "baseUnitValue");@"
- case $unitEnumName.$($unit.SingularName): return $func;
-"@; }@"
- default:
- throw new NotImplementedException($"Can not convert {Unit} to {unit}.");
- }
- }
-
- #endregion
-"@;
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateStaticQuantitySourceCode.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateStaticQuantitySourceCode.ps1
deleted file mode 100644
index 34b6eedd92..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateStaticQuantitySourceCode.ps1
+++ /dev/null
@@ -1,123 +0,0 @@
-using module ".\Types.psm1"
-
-function GenerateStaticQuantitySourceCode([Quantity[]]$quantities, [string]$target)
-{
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using System.Linq;
-using JetBrains.Annotations;
-using UnitsNet.InternalHelpers;
-using UnitsNet.Units;
-
-namespace UnitsNet
-{
- ///
- /// Dynamically parse or construct quantities when types are only known at runtime.
- ///
- internal static partial class Quantity
- {
- ///
- /// Try to dynamically construct a quantity.
- ///
- /// Numeric value.
- /// Unit enum value.
- /// The resulting quantity if successful, otherwise default.
- /// True if successful with assigned the value, otherwise false.
- internal static bool TryFrom(double value, Enum unit, out IQuantity quantity)
- {
- switch (unit)
- {
-"@; foreach ($quantity in $quantities) {
- $quantityName = $quantity.Name
- $unitTypeName = $quantityName + "Unit"
- $unitValue = toCamelCase($unitTypeName);@"
- case $unitTypeName $($unitValue):
- quantity = $quantityName.From(value, $unitValue);
- return true;
-"@; }@"
- default:
- {
- quantity = default(IQuantity);
- return false;
- }
- }
- }
-
- ///
- internal static IQuantity Parse(Type quantityType, string quantityString) => Parse(null, quantityType, quantityString);
-
- ///
- /// Dynamically parse a quantity string representation.
- ///
- /// The format provider to use for lookup. Defaults to if null.
- /// Type of quantity, such as .
- /// Quantity string representation, such as "1.5 kg". Must be compatible with given quantity type.
- /// The parsed quantity.
- /// Type must be of type UnitsNet.IQuantity -or- Type is not a known quantity type.
- internal static IQuantity Parse([CanBeNull] IFormatProvider formatProvider, Type quantityType, string quantityString)
- {
- if (!typeof(IQuantity).Wrap().IsAssignableFrom(quantityType))
- throw new ArgumentException($"Type {quantityType} must be of type UnitsNet.IQuantity.");
-
- if (TryParse(formatProvider, quantityType, quantityString, out IQuantity quantity)) return quantity;
-
- throw new ArgumentException($"Quantity string could not be parsed to quantity {quantityType}.");
- }
-
- ///
- internal static bool TryParse(Type quantityType, string quantityString, out IQuantity quantity) =>
- TryParse(null, quantityType, quantityString, out quantity);
-
- ///
- /// Try to dynamically parse a quantity string representation.
- ///
- /// The format provider to use for lookup. Defaults to if null.
- /// Type of quantity, such as .
- /// Quantity string representation, such as "1.5 kg". Must be compatible with given quantity type.
- /// The resulting quantity if successful, otherwise default.
- /// The parsed quantity.
- internal static bool TryParse([CanBeNull] IFormatProvider formatProvider, Type quantityType, string quantityString, out IQuantity quantity)
- {
- quantity = default(IQuantity);
-
- if (!typeof(IQuantity).Wrap().IsAssignableFrom(quantityType))
- return false;
-
- var parser = QuantityParser.Default;
-
-"@; foreach ($quantity in $quantities) {
- $quantityName = $quantity.Name;@"
- if (quantityType == typeof($quantityName))
- return parser.TryParse<$quantityName, $($quantityName)Unit>(quantityString, formatProvider, $quantityName.From, out quantity);
-
-"@; }@"
- throw new ArgumentException(
- $"Type {quantityType} is not a known quantity type. Did you pass in a third-party quantity type defined outside UnitsNet library?");
- }
- }
-}
-"@;
-}
-
-function toCamelCase([string] $str) {
- return [char]::ToLower($str[0]) + $str.Substring(1)
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateTemplates.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateTemplates.ps1
deleted file mode 100644
index f6b2d15ce7..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateTemplates.ps1
+++ /dev/null
@@ -1,13 +0,0 @@
-<#
-.SYNOPSIS
-Returns the Obsolete attribute if ObsoleteText has been defined on the JSON input - otherwise returns empty string
-It is up to the consumer to wrap any padding/new lines in order to keep to correct indentation formats
-#>
-function GetObsoleteAttribute($quantityOrUnit)
-{
- if ($quantityOrUnit.ObsoleteText)
- {
- return "[System.Obsolete(""$($quantityOrUnit.ObsoleteText)"")]";
- }
- return "";
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1
deleted file mode 100644
index 5220b72310..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-function GenerateUnitSystemDefaultSourceCode($quantities)
-{
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using UnitsNet.Units;
-
-// ReSharper disable RedundantCommaInArrayInitializer
-// ReSharper disable once CheckNamespace
-namespace UnitsNet
-{
- public sealed partial class UnitAbbreviationsCache
- {
- private static readonly (string CultureName, Type UnitType, int UnitValue, string[] UnitAbbreviations)[] GeneratedLocalizations
- = new []
- {
-"@;
- foreach ($quantity in $quantities)
- {
- $quantityName = $quantity.Name;
- $unitEnumName = "$quantityName" + "Unit";
-
- foreach ($unit in $quantity.Units)
- {
- $enumValue = $unit.SingularName;
-
- foreach ($localization in $unit.Localization)
- {
- $cultureName = $localization.Culture;
- $abbreviationParams = $localization.Abbreviations -join '", "'
-@"
- (`"$cultureName`", typeof($unitEnumName), (int)$unitEnumName.$enumValue, new string[]{`"$abbreviationParams`"}),
-"@;
- }
- }
- }
-@"
- };
- }
-}
-"@;
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1
deleted file mode 100644
index 71a80f1db7..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1
+++ /dev/null
@@ -1,300 +0,0 @@
-using module ".\Types.psm1"
-function GenerateUnitTestBaseClassSourceCode([Quantity]$quantity)
-{
- $quantityName = $quantity.Name
- $units = $quantity.Units
- $valueType = $quantity.BaseType
- [Unit]$baseUnit = $units | where { $_.SingularName -eq $quantity.BaseUnit } | Select-Object -First 1
- $baseUnitSingularName = $baseUnit.SingularName
- $baseUnitPluralName = $baseUnit.PluralName
- $baseUnitVariableName = $baseUnitSingularName.ToLowerInvariant()
- $unitEnumName = "$quantityName" + "Unit"
-
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using System.Linq;
-using UnitsNet.Units;
-using Xunit;
-
-// Disable build warning CS1718: Comparison made to same variable; did you mean to compare something else?
-#pragma warning disable 1718
-
-// ReSharper disable once CheckNamespace
-namespace UnitsNet.Tests
-{
- ///
- /// Test of $quantityName.
- ///
-// ReSharper disable once PartialTypeWithSinglePart
- public abstract partial class $($quantityName)TestsBase
- {
-"@; foreach ($unit in $units) {@"
- protected abstract double $($unit.PluralName)InOne$($baseUnit.SingularName) { get; }
-"@; }@"
-
-// ReSharper disable VirtualMemberNeverOverriden.Global
-"@; foreach ($unit in $units) {@"
- protected virtual double $($unit.PluralName)Tolerance { get { return 1e-5; } }
-"@; }@"
-// ReSharper restore VirtualMemberNeverOverriden.Global
-
- [Fact]
- public void Ctor_WithUndefinedUnit_ThrowsArgumentException()
- {
- Assert.Throws(() => new $quantityName(($valueType)0.0, $unitEnumName.Undefined));
- }
-
-"@; if ($quantity.BaseType -eq "double") {@"
- [Fact]
- public void Ctor_WithInfinityValue_ThrowsArgumentException()
- {
- Assert.Throws(() => new $quantityName(double.PositiveInfinity, $unitEnumName.$($baseUnit.SingularName)));
- Assert.Throws(() => new $quantityName(double.NegativeInfinity, $unitEnumName.$($baseUnit.SingularName)));
- }
-
- [Fact]
- public void Ctor_WithNaNValue_ThrowsArgumentException()
- {
- Assert.Throws(() => new $quantityName(double.NaN, $unitEnumName.$($baseUnit.SingularName)));
- }
-"@; }@"
-
- [Fact]
- public void $($baseUnit.SingularName)To$($quantityName)Units()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance($($unit.PluralName)InOne$($baseUnit.SingularName), $baseUnitVariableName.$($unit.PluralName), $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
- [Fact]
- public void FromValueAndUnit()
- {
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance(1, $quantityName.From(1, $unitEnumName.$($unit.SingularName)).$($unit.PluralName), $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
-"@; if ($quantity.BaseType -eq "double") {@"
- [Fact]
- public void From$($baseUnit.PluralName)_WithInfinityValue_ThrowsArgumentException()
- {
- Assert.Throws(() => $quantityName.From$($baseUnit.PluralName)(double.PositiveInfinity));
- Assert.Throws(() => $quantityName.From$($baseUnit.PluralName)(double.NegativeInfinity));
- }
-
- [Fact]
- public void From$($baseUnit.PluralName)_WithNanValue_ThrowsArgumentException()
- {
- Assert.Throws(() => $quantityName.From$($baseUnit.PluralName)(double.NaN));
- }
-"@; }@"
-
- [Fact]
- public void As()
- {
- var $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance($($unit.PluralName)InOne$($baseUnit.SingularName), $baseUnitVariableName.As($($quantityName)Unit.$($unit.SingularName)), $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
- [Fact]
- public void ToUnit()
- {
- var $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units)
-{
- $asQuantityVariableName = "$($unit.SingularName.ToLowerInvariant())Quantity";
-@"
-
- var $asQuantityVariableName = $baseUnitVariableName.ToUnit($($quantityName)Unit.$($unit.SingularName));
- AssertEx.EqualTolerance($($unit.PluralName)InOne$($baseUnit.SingularName), (double)$asQuantityVariableName.Value, $($unit.PluralName)Tolerance);
- Assert.Equal($($quantityName)Unit.$($unit.SingularName), $asQuantityVariableName.Unit);
-"@; }@"
- }
-
- [Fact]
- public void ConversionRoundTrip()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance(1, $quantityName.From$($unit.PluralName)($baseUnitVariableName.$($unit.PluralName)).$baseUnitPluralName, $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
-"@; if ($quantity.Logarithmic -eq $true) {@"
- [Fact]
- public void LogarithmicArithmeticOperators()
- {
- $quantityName v = $quantityName.From$baseUnitPluralName(40);
- AssertEx.EqualTolerance(-40, -v.$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertLogarithmicAddition();
- AssertLogarithmicSubtraction();
- AssertEx.EqualTolerance(50, (v*10).$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertEx.EqualTolerance(50, (10*v).$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertEx.EqualTolerance(35, (v/5).$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertEx.EqualTolerance(35, v/$quantityName.From$baseUnitPluralName(5), $($unit.PluralName)Tolerance);
- }
-
- protected abstract void AssertLogarithmicAddition();
-
- protected abstract void AssertLogarithmicSubtraction();
-
-"@; }
- elseif ($quantity.GenerateArithmetic -eq $true) {@"
- [Fact]
- public void ArithmeticOperators()
- {
- $quantityName v = $quantityName.From$baseUnitPluralName(1);
- AssertEx.EqualTolerance(-1, -v.$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, ($quantityName.From$baseUnitPluralName(3)-v).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, (v + v).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(10, (v*10).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(10, (10*v).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, ($quantityName.From$baseUnitPluralName(10)/5).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, $quantityName.From$baseUnitPluralName(10)/$quantityName.From$baseUnitPluralName(5), $($baseUnit.PluralName)Tolerance);
- }
-"@; }@"
-
- [Fact]
- public void ComparisonOperators()
- {
- $quantityName one$($baseUnit.SingularName) = $quantityName.From$baseUnitPluralName(1);
- $quantityName two$baseUnitPluralName = $quantityName.From$baseUnitPluralName(2);
-
- Assert.True(one$($baseUnit.SingularName) < two$baseUnitPluralName);
- Assert.True(one$($baseUnit.SingularName) <= two$baseUnitPluralName);
- Assert.True(two$baseUnitPluralName > one$($baseUnit.SingularName));
- Assert.True(two$baseUnitPluralName >= one$($baseUnit.SingularName));
-
- Assert.False(one$($baseUnit.SingularName) > two$baseUnitPluralName);
- Assert.False(one$($baseUnit.SingularName) >= two$baseUnitPluralName);
- Assert.False(two$baseUnitPluralName < one$($baseUnit.SingularName));
- Assert.False(two$baseUnitPluralName <= one$($baseUnit.SingularName));
- }
-
- [Fact]
- public void CompareToIsImplemented()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.Equal(0, $baseUnitVariableName.CompareTo($baseUnitVariableName));
- Assert.True($baseUnitVariableName.CompareTo($quantityName.Zero) > 0);
- Assert.True($quantityName.Zero.CompareTo($baseUnitVariableName) < 0);
- }
-
- [Fact]
- public void CompareToThrowsOnTypeMismatch()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.Throws(() => $baseUnitVariableName.CompareTo(new object()));
- }
-
- [Fact]
- public void CompareToThrowsOnNull()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.Throws(() => $baseUnitVariableName.CompareTo(null));
- }
-
- [Fact]
- public void EqualityOperators()
- {
- var a = $quantityName.From$baseUnitPluralName(1);
- var b = $quantityName.From$baseUnitPluralName(2);
-
- // ReSharper disable EqualExpressionComparison
-
- Assert.True(a == a);
- Assert.False(a != a);
-
- Assert.True(a != b);
- Assert.False(a == b);
-
- Assert.False(a == null);
- Assert.False(null == a);
-
-// ReSharper restore EqualExpressionComparison
- }
-
- [Fact]
- public void EqualsIsImplemented()
- {
- var a = $quantityName.From$baseUnitPluralName(1);
- var b = $quantityName.From$baseUnitPluralName(2);
-
- Assert.True(a.Equals(a));
- Assert.False(a.Equals(b));
- Assert.False(a.Equals(null));
- }
-
- [Fact]
- public void EqualsRelativeToleranceIsImplemented()
- {
- var v = $quantityName.From$baseUnitPluralName(1);
- Assert.True(v.Equals($quantityName.From$baseUnitPluralName(1), $($baseUnitPluralName)Tolerance, ComparisonType.Relative));
- Assert.False(v.Equals($quantityName.Zero, $($baseUnitPluralName)Tolerance, ComparisonType.Relative));
- }
-
- [Fact]
- public void EqualsReturnsFalseOnTypeMismatch()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.False($baseUnitVariableName.Equals(new object()));
- }
-
- [Fact]
- public void EqualsReturnsFalseOnNull()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.False($baseUnitVariableName.Equals(null));
- }
-
- [Fact]
- public void UnitsDoesNotContainUndefined()
- {
- Assert.DoesNotContain($unitEnumName.Undefined, $quantityName.Units);
- }
-
- [Fact]
- public void HasAtLeastOneAbbreviationSpecified()
- {
- var units = Enum.GetValues(typeof($unitEnumName)).Cast<$unitEnumName>();
- foreach(var unit in units)
- {
- if(unit == $unitEnumName.Undefined)
- continue;
-
- var defaultAbbreviation = UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit);
- }
- }
-
- [Fact]
- public void BaseDimensionsShouldNeverBeNull()
- {
- Assert.False($quantityName.BaseDimensions is null);
- }
- }
-}
-"@;
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTestPlaceholderSourceCode.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTestPlaceholderSourceCode.ps1
deleted file mode 100644
index 055b2bfc8e..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTestPlaceholderSourceCode.ps1
+++ /dev/null
@@ -1,37 +0,0 @@
-function GenerateUnitTestPlaceholderSourceCode($quantity)
-{
- $quantityName = $quantity.Name;
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated (once) by \generate-code.bat, but will not be
-// regenerated when it already exists. The purpose of creating this file is to make
-// it easier to remember to implement all the unit conversion test cases.
-//
-// Whenever a new unit is added to this quantity and \generate-code.bat is run,
-// the base test class will get a new abstract property and cause a compile error
-// in this derived class, reminding the developer to implement the test case
-// for the new unit.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-
-namespace UnitsNet.Tests.CustomCode
-{
- public class $($quantityName)Tests : $($quantityName)TestsBase
- {
- // Override properties in base class here
- }
-}
-"@;
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTypeSourceCode.ps1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTypeSourceCode.ps1
deleted file mode 100644
index 047f218560..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Include-GenerateUnitTypeSourceCode.ps1
+++ /dev/null
@@ -1,56 +0,0 @@
-function GenerateUnitTypeSourceCode($quantity) {
- $quantityName = $quantity.Name;
- $units = $quantity.Units;
- $unitEnumName = "$($quantityName)Unit";
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-// ReSharper disable once CheckNamespace
-namespace UnitsNet.Units
-{
- // Disable missing XML comment warnings for the generated unit enums.
- #pragma warning disable 1591
-
- public enum $unitEnumName
- {
- Undefined = 0,
-"@; foreach ($unit in $units) {
- $obsoleteAttribute = GetObsoleteAttribute($unit);
-
- if ($unit.XmlDocSummary) {@"
-
- ///
- /// $($unit.XmlDocSummary)
- ///
-"@; }
- if ($unit.XmlDocRemarks) {@"
- /// $($unit.XmlDocRemarks)
-"@; }
- if ($obsoleteAttribute) {@"
- $($obsoleteAttribute)
-"@; }@"
- $($unit.SingularName),
-"@; }@"
- }
-
- #pragma warning restore 1591
-}
-"@;
-}
diff --git a/UnitsNet.WindowsRuntimeComponent/Scripts/Types.psm1 b/UnitsNet.WindowsRuntimeComponent/Scripts/Types.psm1
deleted file mode 100644
index 7dfae70090..0000000000
--- a/UnitsNet.WindowsRuntimeComponent/Scripts/Types.psm1
+++ /dev/null
@@ -1,50 +0,0 @@
-class Quantity
-{
- [string]$Name
- [string]$XmlDocSummary
- [string]$XmlDocRemarks
- [string]$BaseUnit
- [string]$BaseType # TODO Rename me to ValueType
- [BaseDimensions]$BaseDimensions = [BaseDimensions]::new()
- [boolean]$GenerateArithmetic = $true
- [boolean]$Logarithmic = $false
- [int]$LogarithmicScalingFactor = 1
- [Unit[]]$Units = @()
-}
-
-class Unit
-{
- [string]$SingularName
- [string]$PluralName
- [string]$XmlDocSummary
- [string]$XmlDocRemarks
- [string]$FromUnitToBaseFunc
- [string]$FromBaseToUnitFunc
- [string[]]$Prefixes = @()
- [Localization[]]$Localization = @()
-}
-
-class Localization
-{
- [string]$Culture
- [string[]]$Abbreviations = @()
- [object[]]$AbbreviationsWithPrefixes = @()
-}
-
-class BaseDimensions
-{
- [int]$Length = 0
- [int]$Mass = 0
- [int]$Time = 0
- [int]$ElectricCurrent = 0
- [int]$Temperature = 0
- [int]$AmountOfSubstance = 0
- [int]$LuminousIntensity = 0
-}
-
-class GeneratorArgs
-{
- [Quantity]$Quantity
- [Unit]$BaseUnit
- [string]$UnitEnumName
-}
diff --git a/UnitsNet.sln b/UnitsNet.sln
index f827f95b70..4553cef60d 100644
--- a/UnitsNet.sln
+++ b/UnitsNet.sln
@@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitsNet.Tests", "UnitsNet.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitsNet.Serialization.JsonNet.CompatibilityTests", "UnitsNet.Serialization.JsonNet.CompatibilityTests\UnitsNet.Serialization.JsonNet.CompatibilityTests.csproj", "{21F2FFAC-BF39-487F-9ADE-37100162F955}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeGen", "CodeGen\CodeGen.csproj", "{078E3D44-4F60-46B3-9099-91A7CBF0B213}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -39,6 +41,10 @@ Global
{21F2FFAC-BF39-487F-9ADE-37100162F955}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21F2FFAC-BF39-487F-9ADE-37100162F955}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21F2FFAC-BF39-487F-9ADE-37100162F955}.Release|Any CPU.Build.0 = Release|Any CPU
+ {078E3D44-4F60-46B3-9099-91A7CBF0B213}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {078E3D44-4F60-46B3-9099-91A7CBF0B213}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {078E3D44-4F60-46B3-9099-91A7CBF0B213}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {078E3D44-4F60-46B3-9099-91A7CBF0B213}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/UnitsNet.sln.DotSettings b/UnitsNet.sln.DotSettings
index 40954ed83d..0990561af3 100644
--- a/UnitsNet.sln.DotSettings
+++ b/UnitsNet.sln.DotSettings
@@ -17,4 +17,7 @@
True
True
True
- True
+ True
+ True
+ True
+ True
diff --git a/UnitsNet/GeneratedCode/UnitAbbreviationsCache.g.cs b/UnitsNet/GeneratedCode/UnitAbbreviationsCache.g.cs
index c2915b9da4..c25849931d 100644
--- a/UnitsNet/GeneratedCode/UnitAbbreviationsCache.g.cs
+++ b/UnitsNet/GeneratedCode/UnitAbbreviationsCache.g.cs
@@ -71,18 +71,15 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Degree, new string[]{"°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Gradian, new string[]{"g"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Gradian, new string[]{"g"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µ°"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µdeg"}),
+ ("en-US", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µ°", "µdeg"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Microdegree, new string[]{"µ°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Microradian, new string[]{"µrad"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Microradian, new string[]{"µрад"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"m°"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"mdeg"}),
+ ("en-US", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"m°", "mdeg"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Millidegree, new string[]{"m°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Milliradian, new string[]{"mrad"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Milliradian, new string[]{"mрад"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"n°"}),
- ("en-US", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"ndeg"}),
+ ("en-US", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"n°", "ndeg"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Nanodegree, new string[]{"n°"}),
("en-US", typeof(AngleUnit), (int)AngleUnit.Nanoradian, new string[]{"nrad"}),
("ru-RU", typeof(AngleUnit), (int)AngleUnit.Nanoradian, new string[]{"nрад"}),
@@ -129,41 +126,29 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(AreaMomentOfInertiaUnit), (int)AreaMomentOfInertiaUnit.MillimeterToTheFourth, new string[]{"mm⁴", "mm^4"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.BitPerSecond, new string[]{"bit/s", "bps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.BytePerSecond, new string[]{"B/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabitPerSecond, new string[]{"Ebit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabitPerSecond, new string[]{"Ebps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabitPerSecond, new string[]{"Ebit/s", "Ebps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExabytePerSecond, new string[]{"EB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibitPerSecond, new string[]{"Eibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibitPerSecond, new string[]{"Eibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibitPerSecond, new string[]{"Eibit/s", "Eibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.ExbibytePerSecond, new string[]{"EiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibitPerSecond, new string[]{"Gibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibitPerSecond, new string[]{"Gibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibitPerSecond, new string[]{"Gibit/s", "Gibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.GibibytePerSecond, new string[]{"GiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabitPerSecond, new string[]{"Gbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabitPerSecond, new string[]{"Gbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabitPerSecond, new string[]{"Gbit/s", "Gbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.GigabytePerSecond, new string[]{"GB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibitPerSecond, new string[]{"Kibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibitPerSecond, new string[]{"Kibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibitPerSecond, new string[]{"Kibit/s", "Kibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.KibibytePerSecond, new string[]{"KiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobitPerSecond, new string[]{"kbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobitPerSecond, new string[]{"kbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobitPerSecond, new string[]{"kbit/s", "kbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.KilobytePerSecond, new string[]{"kB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibitPerSecond, new string[]{"Mibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibitPerSecond, new string[]{"Mibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibitPerSecond, new string[]{"Mibit/s", "Mibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.MebibytePerSecond, new string[]{"MiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabitPerSecond, new string[]{"Mbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabitPerSecond, new string[]{"Mbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabitPerSecond, new string[]{"Mbit/s", "Mbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.MegabytePerSecond, new string[]{"MB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibitPerSecond, new string[]{"Pibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibitPerSecond, new string[]{"Pibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibitPerSecond, new string[]{"Pibit/s", "Pibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.PebibytePerSecond, new string[]{"PiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabitPerSecond, new string[]{"Pbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabitPerSecond, new string[]{"Pbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabitPerSecond, new string[]{"Pbit/s", "Pbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.PetabytePerSecond, new string[]{"PB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibitPerSecond, new string[]{"Tibit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibitPerSecond, new string[]{"Tibps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibitPerSecond, new string[]{"Tibit/s", "Tibps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.TebibytePerSecond, new string[]{"TiB/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabitPerSecond, new string[]{"Tbit/s"}),
- ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabitPerSecond, new string[]{"Tbps"}),
+ ("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabitPerSecond, new string[]{"Tbit/s", "Tbps"}),
("en-US", typeof(BitRateUnit), (int)BitRateUnit.TerabytePerSecond, new string[]{"TB/s"}),
("en-US", typeof(BrakeSpecificFuelConsumptionUnit), (int)BrakeSpecificFuelConsumptionUnit.GramPerKiloWattHour, new string[]{"g/kWh"}),
("en-US", typeof(BrakeSpecificFuelConsumptionUnit), (int)BrakeSpecificFuelConsumptionUnit.KilogramPerJoule, new string[]{"kg/J"}),
@@ -226,37 +211,16 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Day, new string[]{"д"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Hour, new string[]{"h", "hr", "hrs", "hour", "hours"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Hour, new string[]{"ч"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µsec"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µsecs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µsecond"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µseconds"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мкс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мксек"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мкс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мксек"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"ms"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"msec"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"msecs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"msecond"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"mseconds"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мсек"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мсек"}),
+ ("en-US", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"µs", "µsec", "µsecs", "µsecond", "µseconds"}),
+ ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Microsecond, new string[]{"мкс", "мксек"}),
+ ("en-US", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"ms", "msec", "msecs", "msecond", "mseconds"}),
+ ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Millisecond, new string[]{"мс", "мсек"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Minute, new string[]{"m", "min", "minute", "minutes"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Minute, new string[]{"мин"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Month30, new string[]{"mo", "month", "months"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Month30, new string[]{"месяц"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"ns"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nsec"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nsecs"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nsecond"}),
- ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"nseconds"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нсек"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нс"}),
- ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нсек"}),
+ ("en-US", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"ns", "nsec", "nsecs", "nsecond", "nseconds"}),
+ ("ru-RU", typeof(DurationUnit), (int)DurationUnit.Nanosecond, new string[]{"нс", "нсек"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Second, new string[]{"s", "sec", "secs", "second", "seconds"}),
("ru-RU", typeof(DurationUnit), (int)DurationUnit.Second, new string[]{"с", "сек"}),
("en-US", typeof(DurationUnit), (int)DurationUnit.Week, new string[]{"wk", "week", "weeks"}),
@@ -592,18 +556,14 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(MassUnit), (int)MassUnit.Hectogram, new string[]{"гг"}),
("en-US", typeof(MassUnit), (int)MassUnit.Kilogram, new string[]{"kg"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Kilogram, new string[]{"кг"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klb"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klbs"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klbm"}),
+ ("en-US", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"klb", "klbs", "klbm"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Kilopound, new string[]{"kфунт"}),
("en-US", typeof(MassUnit), (int)MassUnit.Kilotonne, new string[]{"kt"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Kilotonne, new string[]{"кт"}),
("en-US", typeof(MassUnit), (int)MassUnit.LongHundredweight, new string[]{"cwt"}),
("en-US", typeof(MassUnit), (int)MassUnit.LongTon, new string[]{"long tn"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.LongTon, new string[]{"тонна большая"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlb"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlbs"}),
- ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlbm"}),
+ ("en-US", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mlb", "Mlbs", "Mlbm"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Megapound, new string[]{"Mфунт"}),
("en-US", typeof(MassUnit), (int)MassUnit.Megatonne, new string[]{"Mt"}),
("ru-RU", typeof(MassUnit), (int)MassUnit.Megatonne, new string[]{"Мт"}),
@@ -760,20 +720,14 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(MolarEntropyUnit), (int)MolarEntropyUnit.JoulePerMoleKelvin, new string[]{"J/(mol*K)"}),
("en-US", typeof(MolarEntropyUnit), (int)MolarEntropyUnit.KilojoulePerMoleKelvin, new string[]{"kJ/(mol*K)"}),
("en-US", typeof(MolarEntropyUnit), (int)MolarEntropyUnit.MegajoulePerMoleKelvin, new string[]{"MJ/(mol*K)"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.CentimolesPerLiter, new string[]{"cmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.CentimolesPerLiter, new string[]{"cM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.DecimolesPerLiter, new string[]{"dmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.DecimolesPerLiter, new string[]{"dM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MicromolesPerLiter, new string[]{"µmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MicromolesPerLiter, new string[]{"µM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MillimolesPerLiter, new string[]{"mmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MillimolesPerLiter, new string[]{"mM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.CentimolesPerLiter, new string[]{"cmol/L", "cM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.DecimolesPerLiter, new string[]{"dmol/L", "dM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MicromolesPerLiter, new string[]{"µmol/L", "µM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.MillimolesPerLiter, new string[]{"mmol/L", "mM"}),
("en-US", typeof(MolarityUnit), (int)MolarityUnit.MolesPerCubicMeter, new string[]{"mol/m³"}),
("en-US", typeof(MolarityUnit), (int)MolarityUnit.MolesPerLiter, new string[]{"mol/L", "M"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.NanomolesPerLiter, new string[]{"nmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.NanomolesPerLiter, new string[]{"nM"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.PicomolesPerLiter, new string[]{"pmol/L"}),
- ("en-US", typeof(MolarityUnit), (int)MolarityUnit.PicomolesPerLiter, new string[]{"pM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.NanomolesPerLiter, new string[]{"nmol/L", "nM"}),
+ ("en-US", typeof(MolarityUnit), (int)MolarityUnit.PicomolesPerLiter, new string[]{"pmol/L", "pM"}),
("en-US", typeof(MolarMassUnit), (int)MolarMassUnit.CentigramPerMole, new string[]{"cg/mol"}),
("ru-RU", typeof(MolarMassUnit), (int)MolarMassUnit.CentigramPerMole, new string[]{"сг/моль"}),
("en-US", typeof(MolarMassUnit), (int)MolarMassUnit.DecagramPerMole, new string[]{"dag/mol"}),
@@ -902,7 +856,6 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(PressureUnit), (int)PressureUnit.Kilopascal, new string[]{"кПа"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.KilopoundForcePerSquareFoot, new string[]{"kipf/ft²"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.KilopoundForcePerSquareInch, new string[]{"kipf/in²"}),
- ("en-US", typeof(PressureUnit), (int)PressureUnit.KilopoundForcePerSquareInch, new string[]{"kipf/in²"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.Megabar, new string[]{"Mbar"}),
("ru-RU", typeof(PressureUnit), (int)PressureUnit.Megabar, new string[]{"Mбар"}),
("en-US", typeof(PressureUnit), (int)PressureUnit.MeganewtonPerSquareMeter, new string[]{"MN/m²"}),
@@ -974,18 +927,15 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.DegreePerMinute, new string[]{"°/min", "deg/min"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.DegreePerSecond, new string[]{"°/s", "deg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.DegreePerSecond, new string[]{"°/с"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µ°/s"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µdeg/s"}),
+ ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µ°/s", "µdeg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicrodegreePerSecond, new string[]{"µ°/с"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicroradianPerSecond, new string[]{"µrad/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MicroradianPerSecond, new string[]{"µрад/с"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"m°/s"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"mdeg/s"}),
+ ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"m°/s", "mdeg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MillidegreePerSecond, new string[]{"m°/с"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MilliradianPerSecond, new string[]{"mrad/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.MilliradianPerSecond, new string[]{"mрад/с"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"n°/s"}),
- ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"ndeg/s"}),
+ ("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"n°/s", "ndeg/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanodegreePerSecond, new string[]{"n°/с"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanoradianPerSecond, new string[]{"nrad/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.NanoradianPerSecond, new string[]{"nрад/с"}),
@@ -995,15 +945,11 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.RevolutionPerMinute, new string[]{"об/мин"}),
("en-US", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.RevolutionPerSecond, new string[]{"r/s"}),
("ru-RU", typeof(RotationalSpeedUnit), (int)RotationalSpeedUnit.RevolutionPerSecond, new string[]{"об/с"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.KilonewtonMeterPerRadian, new string[]{"kN·m/rad"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.KilonewtonMeterPerRadian, new string[]{"kNm/rad"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.MeganewtonMeterPerRadian, new string[]{"MN·m/rad"}),
- ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.MeganewtonMeterPerRadian, new string[]{"MNm/rad"}),
+ ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.KilonewtonMeterPerRadian, new string[]{"kN·m/rad", "kNm/rad"}),
+ ("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.MeganewtonMeterPerRadian, new string[]{"MN·m/rad", "MNm/rad"}),
("en-US", typeof(RotationalStiffnessUnit), (int)RotationalStiffnessUnit.NewtonMeterPerRadian, new string[]{"N·m/rad", "Nm/rad"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.KilonewtonMeterPerRadianPerMeter, new string[]{"kN·m/rad/m"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.KilonewtonMeterPerRadianPerMeter, new string[]{"kNm/rad/m"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.MeganewtonMeterPerRadianPerMeter, new string[]{"MN·m/rad/m"}),
- ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.MeganewtonMeterPerRadianPerMeter, new string[]{"MNm/rad/m"}),
+ ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.KilonewtonMeterPerRadianPerMeter, new string[]{"kN·m/rad/m", "kNm/rad/m"}),
+ ("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.MeganewtonMeterPerRadianPerMeter, new string[]{"MN·m/rad/m", "MNm/rad/m"}),
("en-US", typeof(RotationalStiffnessPerLengthUnit), (int)RotationalStiffnessPerLengthUnit.NewtonMeterPerRadianPerMeter, new string[]{"N·m/rad/m", "Nm/rad/m"}),
("en-US", typeof(SolidAngleUnit), (int)SolidAngleUnit.Steradian, new string[]{"sr"}),
("en-US", typeof(SpecificEnergyUnit), (int)SpecificEnergyUnit.BtuPerPound, new string[]{"btu/lb"}),
@@ -1247,9 +1193,7 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.AcreFootPerHour, new string[]{"af/h"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.AcreFootPerMinute, new string[]{"af/m"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.AcreFootPerSecond, new string[]{"af/s"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerDay, new string[]{"cl/day", "cL/d", "cLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CentiliterPerMinute, new string[]{"cLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicDecimeterPerMinute, new string[]{"dm³/min"}),
("ru-RU", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicDecimeterPerMinute, new string[]{"дм³/мин"}),
@@ -1268,13 +1212,9 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicYardPerHour, new string[]{"yd³/h"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicYardPerMinute, new string[]{"yd³/min"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.CubicYardPerSecond, new string[]{"yd³/s"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerDay, new string[]{"dl/day", "dL/d", "dLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.DeciliterPerMinute, new string[]{"dLPM"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerDay, new string[]{"kl/day", "kL/d", "kLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KiloliterPerMinute, new string[]{"kLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.KilousGallonPerMinute, new string[]{"kgal (U.S.)/min", "KGPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerDay, new string[]{"l/day", "L/d", "LPD"}),
@@ -1282,22 +1222,14 @@ private static readonly (string CultureName, Type UnitType, int UnitValue, strin
("ru-RU", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerHour, new string[]{"л/ч"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerMinute, new string[]{"LPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.LiterPerSecond, new string[]{"LPS"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"Ml/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"ML/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"MLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaliterPerDay, new string[]{"Ml/day", "ML/d", "MLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MegaukGallonPerSecond, new string[]{"Mgal (imp.)/s"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerDay, new string[]{"µl/day", "µL/d", "µLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MicroliterPerMinute, new string[]{"µLPM"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"ml/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"mL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"mLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerDay, new string[]{"ml/day", "mL/d", "mLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MilliliterPerMinute, new string[]{"mLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.MillionUsGallonsPerDay, new string[]{"MGD"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nl/day"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nL/d"}),
- ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nLPD"}),
+ ("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerDay, new string[]{"nl/day", "nL/d", "nLPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.NanoliterPerMinute, new string[]{"nLPM"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.OilBarrelPerDay, new string[]{"bbl/d", "BOPD"}),
("en-US", typeof(VolumeFlowUnit), (int)VolumeFlowUnit.OilBarrelPerHour, new string[]{"bbl/hr", "bph"}),
diff --git a/UnitsNet/Scripts/GenerateUnits.ps1 b/UnitsNet/Scripts/GenerateUnits.ps1
deleted file mode 100644
index ca7a0223b9..0000000000
--- a/UnitsNet/Scripts/GenerateUnits.ps1
+++ /dev/null
@@ -1,358 +0,0 @@
-using module ".\Types.psm1"
-
-#Requires -Version 5.1
-
-# Set Write-Output used by Include- files to UTF8 encoding to fix copyright character
-[Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
-$OutputEncoding = [Text.UTF8Encoding]::UTF8
-
-# DaddyCool => daddyCool
-function ToCamelCase($str)
-{
- return $str.Substring(0,1).ToLowerInvariant() + $str.Substring(1)
-}
-
-function ValueOrDefault($value, $defaultValue){
- if ($null -ne $value) { $value } else { $defaultValue }
-}
-
-function Ternary($value, $one, $two){
- if ($value -ne $null) { $one } else { $two }
-}
-
-function GenerateQuantity([Quantity]$quantity, $outDir)
-{
- $outFileName = "$outDir/$($quantity.Name).NetFramework.g.cs"
- GenerateQuantitySourceCode $quantity | Out-File -Encoding "UTF8" $outFileName | Out-Null
- if (!$?) { exit 1 }
- Write-Host -NoNewline "quantity(OK) "
-}
-
-function GenerateUnitTestBaseClass([Quantity]$quantity, $outDir)
-{
- $outFileName = "$outDir/$($quantity.Name)TestsBase.g.cs"
- GenerateUnitTestBaseClassSourceCode $quantity | Out-File -Encoding "UTF8" $outFileName | Out-Null
- if (!$?) {
- exit 1
- }
- Write-Host -NoNewline "test base(OK) "
-}
-
-function GenerateUnitTestClassIfNotExists([Quantity]$quantity, $outDir)
-{
- Write-Host -NoNewline "test stub"
- $outFileName = "$outDir/$($quantity.Name)Tests.cs"
- if (Test-Path $outFileName)
- {
- Write-Host -NoNewline "(skip) "
- return
- }
- else
- {
- GenerateUnitTestPlaceholderSourceCode $quantity | Out-File -Encoding "UTF8" $outFileName | Out-Null
- if (!$?) {
- exit 1
- }
- Write-Host -NoNewline "(OK) "
- }
-}
-
-function GenerateUnitType([Quantity]$quantity, $outDir)
-{
- $outFileName = "$outDir/$($quantity.Name)Unit.g.cs"
-
- GenerateUnitTypeSourceCode $quantity | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- exit 1
- }
- Write-Host -NoNewline "unit(OK) "
-}
-
-function GenerateUnitSystemDefault($quantities, $outDir)
-{
- Write-Host -NoNewline "UnitAbbreviationsCache.g.cs: "
- $outFileName = "$outDir/UnitAbbreviationsCache.g.cs"
-
- GenerateUnitSystemDefaultSourceCode $quantities | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- Write-Host "(error) "
- exit 1
- }
- Write-Host "(OK) "
-}
-
-function GenerateQuantityType($quantities, $outDir)
-{
- Write-Host -NoNewline "QuantityType.g.cs: "
- $outFileName = "$outDir/QuantityType.g.cs"
-
- GenerateQuantityTypeSourceCode $quantities | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- Write-Host "(error) "
- exit 1
- }
- Write-Host "(OK) "
-}
-
-function GenerateStaticQuantity($quantities, $outDir)
-{
- Write-Host -NoNewline "Quantity.g.cs: "
- $outFileName = "$outDir/Quantity.g.cs"
-
- GenerateStaticQuantitySourceCode $quantities | Out-File -Encoding "UTF8" -Force $outFileName | Out-Null
- if (!$?) {
- Write-Host "(error) "
- exit 1
- }
- Write-Host "(OK) "
-}
-
-function EnsureDirExists([String] $dirPath) {
- New-Item -ItemType Directory -Force -Path $dirPath | Out-Null
- if (!$?) {
- exit 1
- }
-}
-
-function Set-ConversionFunctions
-{
- param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $quantity)
- PROCESS {
- foreach ($u in $quantity.Units) {
-
- # Use decimal for internal calculations if base type is not double, such as for long or int.
- if ($quantity.BaseType -eq "decimal") {
- $u.FromUnitToBaseFunc = $u.FromUnitToBaseFunc -replace "d", "m"
- $u.FromBaseToUnitFunc = $u.FromBaseToUnitFunc -replace "d", "m"
- }
-
- # Convert to/from double for other base types
- $u.FromUnitToBaseFunc = "$($u.FromUnitToBaseFunc)"
- $u.FromBaseToUnitFunc = "$($u.FromBaseToUnitFunc)"
- }
- return $quantity
- }
-}
-
-function Add-PrefixUnits {
- param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $quantity)
- PROCESS {
- $prefixUnits = @()
-
- foreach ($unit in $quantity.Units)
- {
- foreach ($localization in $unit.Localization){
- if($localization.AbbreviationsWithPrefixes.Count -gt 0){
- if($unit.Prefixes.Count -ne $localization.AbbreviationsWithPrefixes.Count){
- Write-Error "The prefix count ($($unit.Prefixes.Count)) does not match the abbreviations with prefixes count ($($localization.AbbreviationsWithPrefixes.Count)) for $($quantity.Name).$($unit.SingularName)" -ErrorAction Stop
- }
- }
- }
-
- $prefixIndex = 0
- foreach ($prefix in $unit.Prefixes)
- {
- $prefixInfo = switch ($prefix)
- {
- "Kilo" { "k", "1e3d"; break; }
- "Hecto" { "h", "1e2d"; break; }
- "Deca" { "da", "1e1d"; break; }
- "Deci" { "d", "1e-1d"; break; }
- "Centi" { "c", "1e-2d"; break; }
- "Milli" { "m", "1e-3d"; break; }
- "Micro" { "µ", "1e-6d"; break; }
- "Nano" { "n", "1e-9d"; break; }
-
- # Optimization, move less frequently used prefixes to the end
- "Pico" { "p", "1e-12d"; break; }
- "Femto" { "f", "1e-15d"; break; }
- "Atto" { "a", "1e-18d"; break; }
- "Zepto" { "z", "1e-21d"; break; }
- "Yocto" { "y", "1e-24d"; break; }
-
- "Yotta" { "Y", "1e24d"; break; }
- "Zetta" { "Z", "1e21d"; break; }
- "Exa" { "E", "1e18d"; break; }
- "Peta" { "P", "1e15d"; break; }
- "Tera" { "T", "1e12d"; break; }
- "Giga" { "G", "1e9d"; break; }
- "Mega" { "M", "1e6d"; break; }
-
- # Binary prefixes
- "Kibi" { "Ki", "1024d"; break; }
- "Mebi" { "Mi", "(1024d * 1024)"; break; }
- "Gibi" { "Gi", "(1024d * 1024 * 1024)"; break; }
- "Tebi" { "Ti", "(1024d * 1024 * 1024 * 1024)"; break; }
- "Pebi" { "Pi", "(1024d * 1024 * 1024 * 1024 * 1024)"; break; }
- "Exbi" { "Ei", "(1024d * 1024 * 1024 * 1024 * 1024 * 1024)"; break; }
- }
-
- $prefixAbbreviation = $prefixInfo[0]
- $prefixFactor = $prefixInfo[1]
-
- $prefixUnit = New-Object PsObject -Property @{
- SingularName=$prefix + $(ToCamelCase $unit.SingularName)
- PluralName=$prefix + $(ToCamelCase $unit.PluralName)
- BaseUnits = $null
- FromUnitToBaseFunc="("+$unit.FromUnitToBaseFunc+") * $prefixFactor"
- FromBaseToUnitFunc="("+$unit.FromBaseToUnitFunc+") / $prefixFactor"
-
- Localization=$unit.Localization | % {
- foreach ($abbrSyno in $_.Abbreviations) {
- $abbrev = $prefixAbbreviation + $abbrSyno
- if ($_.AbbreviationsWithPrefixes) {
- if($_.AbbreviationsWithPrefixes[$prefixIndex] -isnot [System.String]){
- foreach($synoWithPrefix in $_.AbbreviationsWithPrefixes[$prefixIndex]){
- New-Object PsObject -Property @{
- Culture=$_.Culture
- Abbreviations= $synoWithPrefix
- }
- }
- continue
- }
- else{
- $abbrev = $_.AbbreviationsWithPrefixes[$prefixIndex]
- }
- }
- New-Object PsObject -Property @{
- Culture=$_.Culture
- Abbreviations= $abbrev
- }
- }
- }
- }
-
- # Append prefix unit
- $prefixUnits += $prefixUnit
- $prefixIndex++;
- } # foreach prefixes
- } # foreach units
-
- $quantity.Units += $prefixUnits
- return $quantity
- }
-}
-
-function Set-UnitsOrderedByName {
- param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $quantity)
- PROCESS {
- $quantity.Units = ($quantity.Units | sort SingularName)
- return $quantity
- }
-}
-
-function Add-InheritedUnits([Quantity]$quantity, $quantities) {
-
- foreach ($inheritFromQuantityName in $quantity.InheritUnitsFrom) {
- $inheritFromQuantity = $quantities | Where { $_.Name -eq $inheritFromQuantityName } | Select -First 1
- $quantity.Units += $inheritFromQuantity.Units
-
- Write-Host -NoNewline "(inherit $inheritFromQuantityName) "
- }
-}
-
-# Load external generator functions with same name as file
-. "$PSScriptRoot/Include-GenerateTemplates.ps1"
-. "$PSScriptRoot/Include-GenerateUnitSystemDefaultSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateQuantityTypeSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateStaticQuantitySourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateQuantitySourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateUnitTypeSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateUnitTestBaseClassSourceCode.ps1"
-. "$PSScriptRoot/Include-GenerateUnitTestPlaceholderSourceCode.ps1"
-
-EnsureDirExists ($quantityDir = "$PSScriptRoot/../GeneratedCode/Quantities")
-EnsureDirExists ($unitEnumDir = "$PSScriptRoot/../GeneratedCode/Units")
-EnsureDirExists ($unitSystemDir = "$PSScriptRoot/../GeneratedCode")
-EnsureDirExists ($testsDir = "$PSScriptRoot/../../UnitsNet.Tests/GeneratedCode")
-EnsureDirExists ($testsCustomCodeDir = "$PSScriptRoot/../../UnitsNet.Tests/CustomCode")
-
-$templatesDir = "$PSScriptRoot/../../Common/UnitDefinitions"
-$pad = 25
-
-# Parse unit definitions from .json files
-# TODO Find a way to automap from JSON into Quantity type
-$quantities = Get-ChildItem -Path $templatesDir -filter "*.json" `
- | %{(Get-Content $_.FullName -Encoding "UTF8" | Out-String)} `
- | ConvertFrom-Json `
- | %{
- # $_ | fl | out-string | write-host -foreground blue
- # New-Object -TypeName Quantity -Verbose -Property @{
- [Quantity]@{
- Name = $_.Name
- XmlDocSummary = $_.XmlDoc
- XmlDocRemarks = $_.XmlDocRemarks
- BaseUnit = $_.BaseUnit
- BaseType = ValueOrDefault $_.BaseType "double"
- BaseDimensions = @{
- Length = ValueOrDefault $_.BaseDimensions.L 0
- Mass = ValueOrDefault $_.BaseDimensions.M 0
- Time = ValueOrDefault $_.BaseDimensions.T 0
- ElectricCurrent = ValueOrDefault $_.BaseDimensions.I 0
- Temperature = ValueOrDefault $_.BaseDimensions.Θ 0
- AmountOfSubstance = ValueOrDefault $_.BaseDimensions.N 0
- LuminousIntensity = ValueOrDefault $_.BaseDimensions.J 0
- }
- GenerateArithmetic = ValueOrDefault $_.GenerateArithmetic $true
- Logarithmic = ValueOrDefault $_.Logarithmic $false
- LogarithmicScalingFactor = ValueOrDefault $_.LogarithmicScalingFactor 1
- Units = $_.Units | %{
- # $_ | fl | out-string | Write-Host -ForegroundColor blue
- [Unit]@{
- SingularName = $_.SingularName
- PluralName = $_.PluralName
- BaseUnits = Ternary $_.BaseUnits @{
- # $_ | fl | out-string | Write-Host -ForegroundColor green
- Length = Ternary $_.BaseUnits.L "length: LengthUnit.$($_.BaseUnits.L)" $null
- Mass = Ternary $_.BaseUnits.M "mass: MassUnit.$($_.BaseUnits.M)" $null
- Time = Ternary $_.BaseUnits.T "time: DurationUnit.$($_.BaseUnits.T)" $null
- ElectricCurrent = Ternary $_.BaseUnits.I "current: ElectricCurrentUnit.$($_.BaseUnits.I)" $null
- Temperature = Ternary $_.BaseUnits.Θ "temperature: TemperatureUnit.$($_.BaseUnits.Θ)" $null
- AmountOfSubstance = Ternary $_.BaseUnits.N "amount: AmountOfSubstanceUnit.$($_.BaseUnits.N)" $null
- LuminousIntensity = Ternary $_.BaseUnits.J "luminousIntensity: LuminousIntensityUnit.$($_.BaseUnits.J)" $null
- } $null
- XmlDocSummary = $_.XmlDocSummary
- XmlDocRemarks = $_.XmlDocRemarks
- FromUnitToBaseFunc = $_.FromUnitToBaseFunc
- FromBaseToUnitFunc = $_.FromBaseToUnitFunc
- Prefixes = [string[]](ValueOrDefault $_.Prefixes @())
- Localization = $_.Localization | %{
- # $_ | fl | out-string | Write-Host -ForegroundColor blue
- [Localization]@{
- Culture = $_.Culture
- Abbreviations = $_.Abbreviations
- AbbreviationsWithPrefixes = $_.AbbreviationsWithPrefixes
- }
- }
- }
- }
- }
- } `
- | Add-PrefixUnits `
- | Set-ConversionFunctions `
- | Set-UnitsOrderedByName
-
-foreach ($quantity in $quantities) {
- Write-Host -NoNewline "$($quantity.Name):".PadRight($pad)
-
- Add-InheritedUnits $quantity $quantities
-
- GenerateQuantity $quantity $quantityDir
- GenerateUnitType $quantity $unitEnumDir
- GenerateUnitTestBaseClass $quantity $testsDir
- GenerateUnitTestClassIfNotExists $quantity $testsCustomCodeDir
-
- Write-Host ""
-}
-
-Write-Host ""
-GenerateUnitSystemDefault $quantities $unitSystemDir
-GenerateQuantityType $quantities $unitSystemDir
-GenerateStaticQuantity $quantities $unitSystemDir
-
-$unitCount = ($quantities | %{$_.Units.Count} | Measure -Sum).Sum
-
-Write-Host "`n`n"
-Write-Host -Foreground Yellow "Summary: $unitCount units in $($quantities.Count) quantities".PadRight($pad)
-Write-Host "`n`n"
-exit 0
diff --git a/UnitsNet/Scripts/Include-GenerateQuantitySourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateQuantitySourceCode.ps1
deleted file mode 100644
index be9b1228fa..0000000000
--- a/UnitsNet/Scripts/Include-GenerateQuantitySourceCode.ps1
+++ /dev/null
@@ -1,1093 +0,0 @@
-using module ".\Types.psm1"
-
-function GenerateQuantitySourceCode([Quantity]$quantity)
-{
- $quantityName = $quantity.Name;
- $units = $quantity.Units;
- $valueType = $quantity.BaseType;
- [Unit]$baseUnit = $units | where { $_.SingularName -eq $quantity.BaseUnit } | Select-Object -First 1
- $baseUnitSingularName = $baseUnit.SingularName
- $baseUnitPluralName = $baseUnit.PluralName
- $unitEnumName = "$quantityName" + "Unit"
-
- $baseDimensions = $quantity.BaseDimensions;
- $isDimensionless = $baseDimensions -eq $null -or ( $baseDimensions.Length -eq 0 -and $baseDimensions.Mass -eq 0 -and $baseDimensions.Time -eq 0 -and $baseDimensions.ElectricCurrent -eq 0 -and $baseDimensions.Temperature -eq 0 -and $baseDimensions.AmountOfSubstance -eq 0 -and $baseDimensions.LuminousIntensity -eq 0 )
-
- [GeneratorArgs]$genArgs = New-Object GeneratorArgs -Property @{
- Quantity = $quantity;
- BaseUnit = $baseUnit;
- UnitEnumName = $unitEnumName;
- }
- # $genArgs | fl | out-string | write-host -foreground yellow
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using System.Globalization;
-using System.Linq;
-using JetBrains.Annotations;
-using UnitsNet.InternalHelpers;
-using UnitsNet.Units;
-
-// ReSharper disable once CheckNamespace
-
-namespace UnitsNet
-{
-"@;
-$obsoleteAttribute = GetObsoleteAttribute($quantity);
-if ($obsoleteAttribute)
-{
- $obsoleteAttribute = "`r`n " + $obsoleteAttribute; # apply padding to conformance with code format in this section
-}
-@"
- ///
- ///
- /// $($quantity.XmlDocSummary)
- ///
-"@; if ($quantity.XmlDocRemarks) {@"
- ///
- /// $($quantity.XmlDocRemarks)
- ///
-"@; }@"
- public partial struct $quantityName : IQuantity<$unitEnumName>, IEquatable<$quantityName>, IComparable, IComparable<$quantityName>, IConvertible, IFormattable
- {
- ///
- /// The numeric value this quantity was constructed with.
- ///
- private readonly $valueType _value;
-
- ///
- /// The unit this quantity was constructed with.
- ///
- private readonly $($unitEnumName)? _unit;
-
- static $quantityName()
- {
-"@; if($isDimensionless) {@"
- BaseDimensions = BaseDimensions.Dimensionless;
-"@; } else {@"
- BaseDimensions = new BaseDimensions($($baseDimensions.Length), $($baseDimensions.Mass), $($baseDimensions.Time), $($baseDimensions.ElectricCurrent), $($baseDimensions.Temperature), $($baseDimensions.AmountOfSubstance), $($baseDimensions.LuminousIntensity));
-"@; }@"
-
- Info = new QuantityInfo<$unitEnumName>(QuantityType.$quantityName,
- new UnitInfo<$unitEnumName>[] {
-"@; foreach ($unit in $units) {
- if($unit.BaseUnits -eq $null){@"
- new UnitInfo<$unitEnumName>($unitEnumName.$($unit.SingularName), BaseUnits.Undefined),
-"@; } else{
- $baseUnitsArray = @($unit.BaseUnits.Length, $unit.BaseUnits.Mass, $unit.BaseUnits.Time, $unit.BaseUnits.ElectricCurrent, $unit.BaseUnits.Temperature, $unit.BaseUnits.AmountOfSubstance, $unit.BaseUnits.LuminousIntensity)
- $baseUnitsArrayFiltered = $baseUnitsArray | Where-Object {$_ -ne ""}
- $baseUnitsConstructorString = $baseUnitsArrayFiltered -join ', ';@"
- new UnitInfo<$unitEnumName>($unitEnumName.$($unit.SingularName), new BaseUnits($baseUnitsConstructorString)),
-"@; }
- }@"
- },
- BaseUnit, Zero, BaseDimensions);
- }
-
- ///
- /// Creates the quantity with the given numeric value and unit.
- ///
- /// The numeric value to contruct this quantity with.
- /// The unit representation to contruct this quantity with.
- /// If value is NaN or Infinity.
- public $quantityName($valueType numericValue, $unitEnumName unit)
- {
- if(unit == $unitEnumName.Undefined)
- throw new ArgumentException("The quantity can not be created with an undefined unit.", nameof(unit));
-
-"@; if ($quantity.BaseType -eq "double") {@"
- _value = Guard.EnsureValidNumber(numericValue, nameof(numericValue));
-"@; } else {@"
- _value = numericValue;
-"@; }@"
- _unit = unit;
- }
-
- ///
- /// Creates an instance of the quantity with the given numeric value in units compatible with the given .
- /// If multiple compatible units were found, the first match is used.
- ///
- /// The numeric value to contruct this quantity with.
- /// The unit system to create the quantity with.
- /// The given is null.
- /// No unit was found for the given .
- public $quantityName($valueType numericValue, UnitSystem unitSystem)
- {
- if(unitSystem == null) throw new ArgumentNullException(nameof(unitSystem));
-
- var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
- var firstUnitInfo = unitInfos.FirstOrDefault();
-
-"@; if ($quantity.BaseType -eq "double") {@"
- _value = Guard.EnsureValidNumber(numericValue, nameof(numericValue));
-"@; } else {@"
- _value = numericValue;
-"@; }@"
- _unit = firstUnitInfo?.Value ?? throw new ArgumentException("No units were found for the given UnitSystem.", nameof(unitSystem));
- }
-"@;
- GenerateStaticProperties $genArgs
- GenerateProperties $genArgs
- GenerateConversionProperties $genArgs
- GenerateStaticMethods $genArgs
- GenerateStaticFactoryMethods $genArgs
- GenerateStaticParseMethods $genArgs
- GenerateArithmeticOperators $genArgs
- GenerateEqualityAndComparison $genArgs
- GenerateConversionMethods $genArgs
-@"
-
- #region ToString Methods
-
- ///
- /// Gets the default string representation of value and unit.
- ///
- /// String representation.
- public override string ToString()
- {
- return ToString("g");
- }
-
- ///
- /// Gets the default string representation of value and unit using the given format provider.
- ///
- /// String representation.
- /// Format to use for localization and number formatting. Defaults to if null.
- public string ToString([CanBeNull] IFormatProvider provider)
- {
- return ToString("g", provider);
- }
-
- ///
- /// Get string representation of value and unit.
- ///
- /// The number of significant digits after the radix point.
- /// String representation.
- /// Format to use for localization and number formatting. Defaults to if null.
- [Obsolete(@"This method is deprecated and will be removed at a future release. Please use ToString(""s2"") or ToString(""s2"", provider) where 2 is an example of the number passed to significantDigitsAfterRadix.")]
- public string ToString([CanBeNull] IFormatProvider provider, int significantDigitsAfterRadix)
- {
- var value = Convert.ToDouble(Value);
- var format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix);
- return ToString(provider, format);
- }
-
- ///
- /// Get string representation of value and unit.
- ///
- /// String format to use. Default: "{0:0.##} {1} for value and unit abbreviation respectively."
- /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1.
- /// String representation.
- /// Format to use for localization and number formatting. Defaults to if null.
- [Obsolete("This method is deprecated and will be removed at a future release. Please use string.Format().")]
- public string ToString([CanBeNull] IFormatProvider provider, [NotNull] string format, [NotNull] params object[] args)
- {
- if (format == null) throw new ArgumentNullException(nameof(format));
- if (args == null) throw new ArgumentNullException(nameof(args));
-
- provider = provider ?? CultureInfo.CurrentUICulture;
-
- var value = Convert.ToDouble(Value);
- var formatArgs = UnitFormatter.GetFormatArgs(Unit, value, provider, args);
- return string.Format(provider, format, formatArgs);
- }
-
- ///
- ///
- /// Gets the string representation of this instance in the specified format string using .
- ///
- /// The format string.
- /// The string representation.
- public string ToString(string format)
- {
- return ToString(format, CultureInfo.CurrentUICulture);
- }
-
- ///
- ///
- /// Gets the string representation of this instance in the specified format string using the specified format provider, or if null.
- ///
- /// The format string.
- /// Format to use for localization and number formatting. Defaults to if null.
- /// The string representation.
- public string ToString(string format, IFormatProvider formatProvider)
- {
- return QuantityFormatter.Format<$unitEnumName>(this, format, formatProvider);
- }
-
- #endregion
-
- #region IConvertible Methods
-
- TypeCode IConvertible.GetTypeCode()
- {
- return TypeCode.Object;
- }
-
- bool IConvertible.ToBoolean(IFormatProvider provider)
- {
- throw new InvalidCastException($"Converting {typeof($quantityName)} to bool is not supported.");
- }
-
- byte IConvertible.ToByte(IFormatProvider provider)
- {
- return Convert.ToByte(_value);
- }
-
- char IConvertible.ToChar(IFormatProvider provider)
- {
- throw new InvalidCastException($"Converting {typeof($quantityName)} to char is not supported.");
- }
-
- DateTime IConvertible.ToDateTime(IFormatProvider provider)
- {
- throw new InvalidCastException($"Converting {typeof($quantityName)} to DateTime is not supported.");
- }
-
- decimal IConvertible.ToDecimal(IFormatProvider provider)
- {
- return Convert.ToDecimal(_value);
- }
-
- double IConvertible.ToDouble(IFormatProvider provider)
- {
- return Convert.ToDouble(_value);
- }
-
- short IConvertible.ToInt16(IFormatProvider provider)
- {
- return Convert.ToInt16(_value);
- }
-
- int IConvertible.ToInt32(IFormatProvider provider)
- {
- return Convert.ToInt32(_value);
- }
-
- long IConvertible.ToInt64(IFormatProvider provider)
- {
- return Convert.ToInt64(_value);
- }
-
- sbyte IConvertible.ToSByte(IFormatProvider provider)
- {
- return Convert.ToSByte(_value);
- }
-
- float IConvertible.ToSingle(IFormatProvider provider)
- {
- return Convert.ToSingle(_value);
- }
-
- string IConvertible.ToString(IFormatProvider provider)
- {
- return ToString("g", provider);
- }
-
- object IConvertible.ToType(Type conversionType, IFormatProvider provider)
- {
- if(conversionType == typeof($quantityName))
- return this;
- else if(conversionType == typeof($unitEnumName))
- return Unit;
- else if(conversionType == typeof(QuantityType))
- return $quantityName.QuantityType;
- else if(conversionType == typeof(BaseDimensions))
- return $quantityName.BaseDimensions;
- else
- throw new InvalidCastException($"Converting {typeof($quantityName)} to {conversionType} is not supported.");
- }
-
- ushort IConvertible.ToUInt16(IFormatProvider provider)
- {
- return Convert.ToUInt16(_value);
- }
-
- uint IConvertible.ToUInt32(IFormatProvider provider)
- {
- return Convert.ToUInt32(_value);
- }
-
- ulong IConvertible.ToUInt64(IFormatProvider provider)
- {
- return Convert.ToUInt64(_value);
- }
-
- #endregion
- }
-}
-"@;
-}
-
-function GenerateStaticProperties([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $baseUnitSingularName = $genArgs.BaseUnit.SingularName
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Static Properties
-
- ///
- public static QuantityInfo<$unitEnumName> Info { get; }
-
- ///
- /// The of this quantity.
- ///
- public static BaseDimensions BaseDimensions { get; }
-
- ///
- /// The base unit of $quantityName, which is $baseUnitSingularName. All conversions go via this value.
- ///
- public static $unitEnumName BaseUnit { get; } = $unitEnumName.$baseUnitSingularName;
-
- ///
- /// Represents the largest possible value of $quantityName
- ///
- public static $quantityName MaxValue { get; } = new $quantityName($valueType.MaxValue, BaseUnit);
-
- ///
- /// Represents the smallest possible value of $quantityName
- ///
- public static $quantityName MinValue { get; } = new $quantityName($valueType.MinValue, BaseUnit);
-
- ///
- /// The of this quantity.
- ///
- public static QuantityType QuantityType { get; } = QuantityType.$quantityName;
-
- ///
- /// All units of measurement for the $quantityName quantity.
- ///
- public static $unitEnumName[] Units { get; } = Enum.GetValues(typeof($unitEnumName)).Cast<$unitEnumName>().Except(new $unitEnumName[]{ $unitEnumName.Undefined }).ToArray();
-
- ///
- /// Gets an instance of this quantity with a value of 0 in the base unit $baseUnitSingularName.
- ///
- public static $quantityName Zero { get; } = new $quantityName(0, BaseUnit);
-
- #endregion
-"@;
-}
-
-function GenerateProperties([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $valueType = $genArgs.Quantity.BaseType
- [bool]$isDoubleValueType = $valueType -eq "double"
-@"
-
- #region Properties
-
- ///
- /// The numeric value this quantity was constructed with.
- ///
- public $valueType Value => _value;
-
-"@; if (-not $isDoubleValueType) { @"
- double IQuantity.Value => (double) _value;
-
-"@; } @"
- Enum IQuantity.Unit => Unit;
-
- ///
- public $unitEnumName Unit => _unit.GetValueOrDefault(BaseUnit);
-
- ///
- public QuantityInfo<$unitEnumName> QuantityInfo => Info;
-
- ///
- QuantityInfo IQuantity.QuantityInfo => Info;
-
- ///
- /// The of this quantity.
- ///
- public QuantityType Type => $quantityName.QuantityType;
-
- ///
- /// The of this quantity.
- ///
- public BaseDimensions Dimensions => $quantityName.BaseDimensions;
-
- #endregion
-"@;
-}
-
-function GenerateConversionProperties([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $units = $genArgs.Quantity.Units
-@"
-
- #region Conversion Properties
-"@;
- foreach ($unit in $units) {
- $propertyName = $unit.PluralName;
- $obsoleteAttribute = GetObsoleteAttribute($unit);
- if ($obsoleteAttribute)
- {
- $obsoleteAttribute = "`r`n " + $obsoleteAttribute; # apply padding to conformance with code format in this page
- }
-@"
-
- ///
- /// Get $quantityName in $propertyName.
- /// $($obsoleteAttribute)
- public double $propertyName => As($unitEnumName.$($unit.SingularName));
-"@; }
-@"
-
- #endregion
-"@;
-}
-
-function GenerateStaticMethods([GeneratorArgs]$genArgs)
-{
- $unitEnumName = $genArgs.UnitEnumName
-@"
-
- #region Static Methods
-
- ///
- /// Get unit abbreviation string.
- ///
- /// Unit to get abbreviation for.
- /// Unit abbreviation string.
- public static string GetAbbreviation($unitEnumName unit)
- {
- return GetAbbreviation(unit, null);
- }
-
- ///
- /// Get unit abbreviation string.
- ///
- /// Unit to get abbreviation for.
- /// Unit abbreviation string.
- /// Format to use for localization. Defaults to if null.
- public static string GetAbbreviation($unitEnumName unit, [CanBeNull] IFormatProvider provider)
- {
- return UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit, provider);
- }
-
- #endregion
-"@;
-}
-
-function GenerateStaticFactoryMethods([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $units = $genArgs.Quantity.Units
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Static Factory Methods
-
-"@; foreach ($unit in $units) {
- $valueParamName = $unit.PluralName.ToLowerInvariant();
- $obsoleteAttribute = GetObsoleteAttribute($unit);
- if ($obsoleteAttribute)
- {
- $obsoleteAttribute = "`r`n " + $obsoleteAttribute; # apply padding to conformance with code format in this page
- }
- @"
- ///
- /// Get $quantityName from $($unit.PluralName).
- /// $($obsoleteAttribute)
- /// If value is NaN or Infinity.
- public static $quantityName From$($unit.PluralName)(QuantityValue $valueParamName)
- {
- $valueType value = ($valueType) $valueParamName;
- return new $quantityName(value, $unitEnumName.$($unit.SingularName));
- }
-"@; }@"
-
- ///
- /// Dynamically convert from value and unit enum to .
- ///
- /// Value to convert from.
- /// Unit to convert from.
- /// $quantityName unit value.
- public static $quantityName From(QuantityValue value, $unitEnumName fromUnit)
- {
- return new $quantityName(($valueType)value, fromUnit);
- }
-
- #endregion
-"@;
-
-}
-
-function GenerateStaticParseMethods([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $baseUnitPluralName = $genArgs.BaseUnit.PluralName
- $units = $genArgs.Quantity.Units
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Static Parse Methods
-
- ///
- /// Parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- ///
- /// Expected string to have one or two pairs of quantity and unit in the format
- /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in"
- ///
- ///
- /// More than one unit is represented by the specified unit abbreviation.
- /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of
- /// , and .
- ///
- ///
- /// If anything else goes wrong, typically due to a bug or unhandled case.
- /// We wrap exceptions in to allow you to distinguish
- /// Units.NET exceptions from other exceptions.
- ///
- public static $quantityName Parse(string str)
- {
- return Parse(str, null);
- }
-
- ///
- /// Parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- ///
- /// Expected string to have one or two pairs of quantity and unit in the format
- /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in"
- ///
- ///
- /// More than one unit is represented by the specified unit abbreviation.
- /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of
- /// , and .
- ///
- ///
- /// If anything else goes wrong, typically due to a bug or unhandled case.
- /// We wrap exceptions in to allow you to distinguish
- /// Units.NET exceptions from other exceptions.
- ///
- /// Format to use when parsing number and unit. Defaults to if null.
- public static $quantityName Parse(string str, [CanBeNull] IFormatProvider provider)
- {
- return QuantityParser.Default.Parse<$quantityName, $unitEnumName>(
- str,
- provider,
- From);
- }
-
- ///
- /// Try to parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- /// Resulting unit quantity if successful.
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- public static bool TryParse([CanBeNull] string str, out $quantityName result)
- {
- return TryParse(str, null, out result);
- }
-
- ///
- /// Try to parse a string with one or two quantities of the format "<quantity> <unit>".
- ///
- /// String to parse. Typically in the form: {number} {unit}
- /// Resulting unit quantity if successful.
- /// True if successful, otherwise false.
- ///
- /// Length.Parse("5.5 m", new CultureInfo("en-US"));
- ///
- /// Format to use when parsing number and unit. Defaults to if null.
- public static bool TryParse([CanBeNull] string str, [CanBeNull] IFormatProvider provider, out $quantityName result)
- {
- return QuantityParser.Default.TryParse<$quantityName, $unitEnumName>(
- str,
- provider,
- From,
- out result);
- }
-
- ///
- /// Parse a unit string.
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.ParseUnit("m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- /// Error parsing string.
- public static $unitEnumName ParseUnit(string str)
- {
- return ParseUnit(str, null);
- }
-
- ///
- /// Parse a unit string.
- ///
- /// String to parse. Typically in the form: {number} {unit}
- ///
- /// Length.ParseUnit("m", new CultureInfo("en-US"));
- ///
- /// The value of 'str' cannot be null.
- /// Error parsing string.
- /// Format to use when parsing number and unit. Defaults to if null.
- public static $unitEnumName ParseUnit(string str, IFormatProvider provider = null)
- {
- return UnitParser.Default.Parse<$unitEnumName>(str, provider);
- }
-
- ///
- public static bool TryParseUnit(string str, out $unitEnumName unit)
- {
- return TryParseUnit(str, null, out unit);
- }
-
- ///
- /// Parse a unit string.
- ///
- /// String to parse. Typically in the form: {number} {unit}
- /// The parsed unit if successful.
- /// True if successful, otherwise false.
- ///
- /// Length.TryParseUnit("m", new CultureInfo("en-US"));
- ///
- /// Format to use when parsing number and unit. Defaults to if null.
- public static bool TryParseUnit(string str, IFormatProvider provider, out $unitEnumName unit)
- {
- return UnitParser.Default.TryParse<$unitEnumName>(str, provider, out unit);
- }
-
- #endregion
-"@;
-}
-
-function GenerateLogarithmicArithmeticOperators([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $valueType = $genArgs.Quantity.BaseType
- $scalingFactor = $genArgs.Quantity.LogarithmicScalingFactor
- # Most logarithmic operators need a simple scaling factor of 10. However, certain units such as voltage ratio need to use 20 instead.
- $x = 10 * $scalingFactor;
- @"
-
- #region Logarithmic Arithmetic Operators
-
- /// Negate the value.
- public static $quantityName operator -($quantityName right)
- {
- return new $quantityName(-right.Value, right.Unit);
- }
-
- /// Get from logarithmic addition of two .
- public static $quantityName operator +($quantityName left, $quantityName right)
- {
- // Logarithmic addition
- // Formula: $x*log10(10^(x/$x) + 10^(y/$x))
- return new $quantityName($x*Math.Log10(Math.Pow(10, left.Value/$x) + Math.Pow(10, right.GetValueAs(left.Unit)/$x)), left.Unit);
- }
-
- /// Get from logarithmic subtraction of two .
- public static $quantityName operator -($quantityName left, $quantityName right)
- {
- // Logarithmic subtraction
- // Formula: $x*log10(10^(x/$x) - 10^(y/$x))
- return new $quantityName($x*Math.Log10(Math.Pow(10, left.Value/$x) - Math.Pow(10, right.GetValueAs(left.Unit)/$x)), left.Unit);
- }
-
- /// Get from logarithmic multiplication of value and .
- public static $quantityName operator *($valueType left, $quantityName right)
- {
- // Logarithmic multiplication = addition
- return new $quantityName(left + right.Value, right.Unit);
- }
-
- /// Get from logarithmic multiplication of value and .
- public static $quantityName operator *($quantityName left, double right)
- {
- // Logarithmic multiplication = addition
- return new $quantityName(left.Value + ($valueType)right, left.Unit);
- }
-
- /// Get from logarithmic division of by value.
- public static $quantityName operator /($quantityName left, double right)
- {
- // Logarithmic division = subtraction
- return new $quantityName(left.Value - ($valueType)right, left.Unit);
- }
-
- /// Get ratio value from logarithmic division of by .
- public static double operator /($quantityName left, $quantityName right)
- {
- // Logarithmic division = subtraction
- return Convert.ToDouble(left.Value - right.GetValueAs(left.Unit));
- }
-
- #endregion
-"@;
-}
-
-function GenerateArithmeticOperators([GeneratorArgs]$genArgs)
-{
- if (-not $quantity.GenerateArithmetic) { return }
-
- # Logarithmic units required different arithmetic
- if ($quantity.Logarithmic) {
- GenerateLogarithmicArithmeticOperators $genArgs
- return
- }
-
- $quantityName = $genArgs.Quantity.Name
- $baseUnitPluralName = $genArgs.BaseUnit.PluralName
- $valueType = $genArgs.Quantity.BaseType
- @"
-
- #region Arithmetic Operators
-
- /// Negate the value.
- public static $quantityName operator -($quantityName right)
- {
- return new $quantityName(-right.Value, right.Unit);
- }
-
- /// Get from adding two .
- public static $quantityName operator +($quantityName left, $quantityName right)
- {
- return new $quantityName(left.Value + right.GetValueAs(left.Unit), left.Unit);
- }
-
- /// Get from subtracting two .
- public static $quantityName operator -($quantityName left, $quantityName right)
- {
- return new $quantityName(left.Value - right.GetValueAs(left.Unit), left.Unit);
- }
-
- /// Get from multiplying value and .
- public static $quantityName operator *($valueType left, $quantityName right)
- {
- return new $quantityName(left * right.Value, right.Unit);
- }
-
- /// Get from multiplying value and .
- public static $quantityName operator *($quantityName left, $valueType right)
- {
- return new $quantityName(left.Value * right, left.Unit);
- }
-
- /// Get from dividing by value.
- public static $quantityName operator /($quantityName left, $valueType right)
- {
- return new $quantityName(left.Value / right, left.Unit);
- }
-
- /// Get ratio value from dividing by .
- public static double operator /($quantityName left, $quantityName right)
- {
- return left.$baseUnitPluralName / right.$baseUnitPluralName;
- }
-
- #endregion
-"@;
-}
-
-function GenerateEqualityAndComparison([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
-@"
-
- #region Equality / IComparable
-
- /// Returns true if less or equal to.
- public static bool operator <=($quantityName left, $quantityName right)
- {
- return left.Value <= right.GetValueAs(left.Unit);
- }
-
- /// Returns true if greater than or equal to.
- public static bool operator >=($quantityName left, $quantityName right)
- {
- return left.Value >= right.GetValueAs(left.Unit);
- }
-
- /// Returns true if less than.
- public static bool operator <($quantityName left, $quantityName right)
- {
- return left.Value < right.GetValueAs(left.Unit);
- }
-
- /// Returns true if greater than.
- public static bool operator >($quantityName left, $quantityName right)
- {
- return left.Value > right.GetValueAs(left.Unit);
- }
-
- /// Returns true if exactly equal.
- /// Consider using for safely comparing floating point values.
- public static bool operator ==($quantityName left, $quantityName right)
- {
- return left.Equals(right);
- }
-
- /// Returns true if not exactly equal.
- /// Consider using for safely comparing floating point values.
- public static bool operator !=($quantityName left, $quantityName right)
- {
- return !(left == right);
- }
-
- ///
- public int CompareTo(object obj)
- {
- if(obj is null) throw new ArgumentNullException(nameof(obj));
- if(!(obj is $quantityName obj$quantityName)) throw new ArgumentException("Expected type $quantityName.", nameof(obj));
-
- return CompareTo(obj$quantityName);
- }
-
- ///
- public int CompareTo($quantityName other)
- {
- return _value.CompareTo(other.GetValueAs(this.Unit));
- }
-
- ///
- /// Consider using for safely comparing floating point values.
- public override bool Equals(object obj)
- {
- if(obj is null || !(obj is $quantityName obj$quantityName))
- return false;
-
- return Equals(obj$quantityName);
- }
-
- ///
- /// Consider using for safely comparing floating point values.
- public bool Equals($quantityName other)
- {
- return _value.Equals(other.GetValueAs(this.Unit));
- }
-
- ///
- ///
- /// Compare equality to another $quantityName within the given absolute or relative tolerance.
- ///
- ///
- /// Relative tolerance is defined as the maximum allowable absolute difference between this quantity's value and
- /// as a percentage of this quantity's value. will be converted into
- /// this quantity's unit for comparison. A relative tolerance of 0.01 means the absolute difference must be within +/- 1% of
- /// this quantity's value to be considered equal.
- ///
- /// In this example, the two quantities will be equal if the value of b is within +/- 1% of a (0.02m or 2cm).
- ///
- /// var a = Length.FromMeters(2.0);
- /// var b = Length.FromInches(50.0);
- /// a.Equals(b, 0.01, ComparisonType.Relative);
- ///
- ///
- ///
- ///
- /// Absolute tolerance is defined as the maximum allowable absolute difference between this quantity's value and
- /// as a fixed number in this quantity's unit. will be converted into
- /// this quantity's unit for comparison.
- ///
- /// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
- ///
- /// var a = Length.FromMeters(2.0);
- /// var b = Length.FromInches(50.0);
- /// a.Equals(b, 0.01, ComparisonType.Absolute);
- ///
- ///
- ///
- ///
- /// Note that it is advised against specifying zero difference, due to the nature
- /// of floating point operations and using System.Double internally.
- ///
- ///
- /// The other quantity to compare to.
- /// The absolute or relative tolerance value. Must be greater than or equal to 0.
- /// The comparison type: either relative or absolute.
- /// True if the absolute difference between the two values is not greater than the specified relative or absolute tolerance.
- public bool Equals($quantityName other, double tolerance, ComparisonType comparisonType)
- {
- if(tolerance < 0)
- throw new ArgumentOutOfRangeException("tolerance", "Tolerance must be greater than or equal to 0.");
-
- double thisValue = (double)this.Value;
- double otherValueInThisUnits = other.As(this.Unit);
-
- return UnitsNet.Comparison.Equals(thisValue, otherValueInThisUnits, tolerance, comparisonType);
- }
-
- ///
- /// Returns the hash code for this instance.
- ///
- /// A hash code for the current $quantityName.
- public override int GetHashCode()
- {
- return new { QuantityType, Value, Unit }.GetHashCode();
- }
-
- #endregion
-"@;
-}
-
-function GenerateConversionMethods([GeneratorArgs]$genArgs)
-{
- $quantityName = $genArgs.Quantity.Name
- $unitEnumName = $genArgs.UnitEnumName
- $valueType = $genArgs.Quantity.BaseType
-@"
-
- #region Conversion Methods
-
- ///
- /// Convert to the unit representation .
- ///
- /// Value converted to the specified unit.
- public double As($unitEnumName unit)
- {
- if(Unit == unit)
- return Convert.ToDouble(Value);
-
- var converted = GetValueAs(unit);
- return Convert.ToDouble(converted);
- }
-
- ///
- public double As(UnitSystem unitSystem)
- {
- if(unitSystem == null)
- throw new ArgumentNullException(nameof(unitSystem));
-
- var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
-
- var firstUnitInfo = unitInfos.FirstOrDefault();
- if(firstUnitInfo == null)
- throw new ArgumentException("No units were found for the given UnitSystem.", nameof(unitSystem));
-
- return As(firstUnitInfo.Value);
- }
-
- ///
- double IQuantity.As(Enum unit)
- {
- if(!(unit is $unitEnumName unitAs$unitEnumName))
- throw new ArgumentException($"The given unit is of type {unit.GetType()}. Only {typeof($unitEnumName)} is supported.", nameof(unit));
-
- return As(unitAs$unitEnumName);
- }
-
- ///
- /// Converts this $quantityName to another $quantityName with the unit representation .
- ///
- /// A $quantityName with the specified unit.
- public $quantityName ToUnit($unitEnumName unit)
- {
- var convertedValue = GetValueAs(unit);
- return new $quantityName(convertedValue, unit);
- }
-
- ///
- IQuantity IQuantity.ToUnit(Enum unit)
- {
- if(!(unit is $unitEnumName unitAs$unitEnumName))
- throw new ArgumentException($"The given unit is of type {unit.GetType()}. Only {typeof($unitEnumName)} is supported.", nameof(unit));
-
- return ToUnit(unitAs$unitEnumName);
- }
-
- ///
- public $quantityName ToUnit(UnitSystem unitSystem)
- {
- if(unitSystem == null)
- throw new ArgumentNullException(nameof(unitSystem));
-
- var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
-
- var firstUnitInfo = unitInfos.FirstOrDefault();
- if(firstUnitInfo == null)
- throw new ArgumentException("No units were found for the given UnitSystem.", nameof(unitSystem));
-
- return ToUnit(firstUnitInfo.Value);
- }
-
- ///
- IQuantity IQuantity.ToUnit(UnitSystem unitSystem) => ToUnit(unitSystem);
-
- ///
- IQuantity<$unitEnumName> IQuantity<$unitEnumName>.ToUnit($unitEnumName unit) => ToUnit(unit);
-
- ///
- IQuantity<$unitEnumName> IQuantity<$unitEnumName>.ToUnit(UnitSystem unitSystem) => ToUnit(unitSystem);
-
- ///
- /// Converts the current value + unit to the base unit.
- /// This is typically the first step in converting from one unit to another.
- ///
- /// The value in the base unit representation.
- private $valueType GetValueInBaseUnit()
- {
- switch(Unit)
- {
-"@; foreach ($unit in $units) {
- $func = $unit.FromUnitToBaseFunc.Replace("x", "_value");@"
- case $unitEnumName.$($unit.SingularName): return $func;
-"@; }@"
- default:
- throw new NotImplementedException($"Can not convert {Unit} to base units.");
- }
- }
-
- private $valueType GetValueAs($unitEnumName unit)
- {
- if(Unit == unit)
- return _value;
-
- var baseUnitValue = GetValueInBaseUnit();
-
- switch(unit)
- {
-"@; foreach ($unit in $units) {
- $func = $unit.FromBaseToUnitFunc.Replace("x", "baseUnitValue");@"
- case $unitEnumName.$($unit.SingularName): return $func;
-"@; }@"
- default:
- throw new NotImplementedException($"Can not convert {Unit} to {unit}.");
- }
- }
-
- #endregion
-"@;
-}
diff --git a/UnitsNet/Scripts/Include-GenerateQuantityTypeSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateQuantityTypeSourceCode.ps1
deleted file mode 100644
index b2364d3118..0000000000
--- a/UnitsNet/Scripts/Include-GenerateQuantityTypeSourceCode.ps1
+++ /dev/null
@@ -1,46 +0,0 @@
-function GenerateQuantityTypeSourceCode($quantities)
-{
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-// ReSharper disable once CheckNamespace
-namespace UnitsNet
-{
- ///
- /// Lists all generated quantities with the same name as the quantity struct type,
- /// such as Length, Mass, Force etc.
- /// This is useful for populating options in the UI, such as creating a generic conversion
- /// tool with inputValue, quantityName, fromUnit and toUnit selectors.
- ///
- public enum QuantityType
- {
-// Missing XML comment for public type or member
-#pragma warning disable CS1591
- Undefined = 0,
-"@; foreach ($quantity in $quantities) {
-@"
- $($quantity.Name),
-"@; }@"
-// Missing XML comment for public type or member
-#pragma warning restore CS1591
- }
-}
-"@;
-}
diff --git a/UnitsNet/Scripts/Include-GenerateStaticQuantitySourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateStaticQuantitySourceCode.ps1
deleted file mode 100644
index d7a52cd54b..0000000000
--- a/UnitsNet/Scripts/Include-GenerateStaticQuantitySourceCode.ps1
+++ /dev/null
@@ -1,120 +0,0 @@
-using module ".\Types.psm1"
-
-function GenerateStaticQuantitySourceCode([Quantity[]]$quantities, [string]$target)
-{
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using System.Globalization;
-using JetBrains.Annotations;
-using UnitsNet.InternalHelpers;
-using UnitsNet.Units;
-
-namespace UnitsNet
-{
- ///
- /// Dynamically parse or construct quantities when types are only known at runtime.
- ///
- public static partial class Quantity
- {
- ///
- /// Dynamically constructs a quantity of the given with the value in the quantity's base units.
- ///
- /// The of the quantity to create.
- /// The value to construct the quantity with.
- /// The created quantity.
- public static IQuantity FromQuantityType(QuantityType quantityType, QuantityValue value)
- {
- switch(quantityType)
- {
-"@; foreach ($quantity in $quantities) {
- $quantityName = $quantity.Name;@"
- case QuantityType.$quantityName`:
- return $quantityName.From(value, $quantityName.BaseUnit);
-"@; }@"
- default:
- throw new ArgumentException($"{quantityType} is not a supported quantity type.");
- }
- }
-
- ///
- /// Try to dynamically construct a quantity.
- ///
- /// Numeric value.
- /// Unit enum value.
- /// The resulting quantity if successful, otherwise default.
- /// True if successful with assigned the value, otherwise false.
- public static bool TryFrom(QuantityValue value, Enum unit, out IQuantity quantity)
- {
- switch (unit)
- {
-"@; foreach ($quantity in $quantities) {
- $quantityName = $quantity.Name
- $unitTypeName = $quantityName + "Unit"
- $unitValue = toCamelCase($unitTypeName);@"
- case $unitTypeName $($unitValue):
- quantity = $quantityName.From(value, $unitValue);
- return true;
-"@; }@"
- default:
- {
- quantity = default(IQuantity);
- return false;
- }
- }
- }
-
- ///
- /// Try to dynamically parse a quantity string representation.
- ///
- /// The format provider to use for lookup. Defaults to if null.
- /// Type of quantity, such as .
- /// Quantity string representation, such as "1.5 kg". Must be compatible with given quantity type.
- /// The resulting quantity if successful, otherwise default.
- /// The parsed quantity.
- public static bool TryParse([CanBeNull] IFormatProvider formatProvider, Type quantityType, string quantityString, out IQuantity quantity)
- {
- quantity = default(IQuantity);
-
- if (!typeof(IQuantity).Wrap().IsAssignableFrom(quantityType))
- return false;
-
- var parser = QuantityParser.Default;
-
- switch(quantityType)
- {
-"@; foreach ($quantity in $quantities) {
- $quantityName = $quantity.Name;@"
- case Type _ when quantityType == typeof($quantityName):
- return parser.TryParse<$quantityName, $($quantityName)Unit>(quantityString, formatProvider, $quantityName.From, out quantity);
-"@; }@"
- default:
- return false;
- }
- }
- }
-}
-"@;
-}
-
-function toCamelCase([string] $str) {
- return [char]::ToLower($str[0]) + $str.Substring(1)
-}
diff --git a/UnitsNet/Scripts/Include-GenerateTemplates.ps1 b/UnitsNet/Scripts/Include-GenerateTemplates.ps1
deleted file mode 100644
index f6b2d15ce7..0000000000
--- a/UnitsNet/Scripts/Include-GenerateTemplates.ps1
+++ /dev/null
@@ -1,13 +0,0 @@
-<#
-.SYNOPSIS
-Returns the Obsolete attribute if ObsoleteText has been defined on the JSON input - otherwise returns empty string
-It is up to the consumer to wrap any padding/new lines in order to keep to correct indentation formats
-#>
-function GetObsoleteAttribute($quantityOrUnit)
-{
- if ($quantityOrUnit.ObsoleteText)
- {
- return "[System.Obsolete(""$($quantityOrUnit.ObsoleteText)"")]";
- }
- return "";
-}
diff --git a/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1
deleted file mode 100644
index e2fea2f963..0000000000
--- a/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-function GenerateUnitSystemDefaultSourceCode($quantities)
-{
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using UnitsNet.Units;
-
-// ReSharper disable RedundantCommaInArrayInitializer
-// ReSharper disable once CheckNamespace
-namespace UnitsNet
-{
- public partial class UnitAbbreviationsCache
- {
- private static readonly (string CultureName, Type UnitType, int UnitValue, string[] UnitAbbreviations)[] GeneratedLocalizations
- = new []
- {
-"@;
- foreach ($quantity in $quantities)
- {
- $quantityName = $quantity.Name;
- $unitEnumName = "$quantityName" + "Unit";
-
- foreach ($unit in $quantity.Units)
- {
- $enumValue = $unit.SingularName;
-
- foreach ($localization in $unit.Localization)
- {
- $cultureName = $localization.Culture;
- $abbreviationParams = $localization.Abbreviations -join '", "'
-@"
- (`"$cultureName`", typeof($unitEnumName), (int)$unitEnumName.$enumValue, new string[]{`"$abbreviationParams`"}),
-"@;
- }
- }
- }
-@"
- };
- }
-}
-"@;
-}
diff --git a/UnitsNet/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1
deleted file mode 100644
index 71a80f1db7..0000000000
--- a/UnitsNet/Scripts/Include-GenerateUnitTestBaseClassSourceCode.ps1
+++ /dev/null
@@ -1,300 +0,0 @@
-using module ".\Types.psm1"
-function GenerateUnitTestBaseClassSourceCode([Quantity]$quantity)
-{
- $quantityName = $quantity.Name
- $units = $quantity.Units
- $valueType = $quantity.BaseType
- [Unit]$baseUnit = $units | where { $_.SingularName -eq $quantity.BaseUnit } | Select-Object -First 1
- $baseUnitSingularName = $baseUnit.SingularName
- $baseUnitPluralName = $baseUnit.PluralName
- $baseUnitVariableName = $baseUnitSingularName.ToLowerInvariant()
- $unitEnumName = "$quantityName" + "Unit"
-
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-using System.Linq;
-using UnitsNet.Units;
-using Xunit;
-
-// Disable build warning CS1718: Comparison made to same variable; did you mean to compare something else?
-#pragma warning disable 1718
-
-// ReSharper disable once CheckNamespace
-namespace UnitsNet.Tests
-{
- ///
- /// Test of $quantityName.
- ///
-// ReSharper disable once PartialTypeWithSinglePart
- public abstract partial class $($quantityName)TestsBase
- {
-"@; foreach ($unit in $units) {@"
- protected abstract double $($unit.PluralName)InOne$($baseUnit.SingularName) { get; }
-"@; }@"
-
-// ReSharper disable VirtualMemberNeverOverriden.Global
-"@; foreach ($unit in $units) {@"
- protected virtual double $($unit.PluralName)Tolerance { get { return 1e-5; } }
-"@; }@"
-// ReSharper restore VirtualMemberNeverOverriden.Global
-
- [Fact]
- public void Ctor_WithUndefinedUnit_ThrowsArgumentException()
- {
- Assert.Throws(() => new $quantityName(($valueType)0.0, $unitEnumName.Undefined));
- }
-
-"@; if ($quantity.BaseType -eq "double") {@"
- [Fact]
- public void Ctor_WithInfinityValue_ThrowsArgumentException()
- {
- Assert.Throws(() => new $quantityName(double.PositiveInfinity, $unitEnumName.$($baseUnit.SingularName)));
- Assert.Throws(() => new $quantityName(double.NegativeInfinity, $unitEnumName.$($baseUnit.SingularName)));
- }
-
- [Fact]
- public void Ctor_WithNaNValue_ThrowsArgumentException()
- {
- Assert.Throws(() => new $quantityName(double.NaN, $unitEnumName.$($baseUnit.SingularName)));
- }
-"@; }@"
-
- [Fact]
- public void $($baseUnit.SingularName)To$($quantityName)Units()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance($($unit.PluralName)InOne$($baseUnit.SingularName), $baseUnitVariableName.$($unit.PluralName), $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
- [Fact]
- public void FromValueAndUnit()
- {
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance(1, $quantityName.From(1, $unitEnumName.$($unit.SingularName)).$($unit.PluralName), $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
-"@; if ($quantity.BaseType -eq "double") {@"
- [Fact]
- public void From$($baseUnit.PluralName)_WithInfinityValue_ThrowsArgumentException()
- {
- Assert.Throws(() => $quantityName.From$($baseUnit.PluralName)(double.PositiveInfinity));
- Assert.Throws(() => $quantityName.From$($baseUnit.PluralName)(double.NegativeInfinity));
- }
-
- [Fact]
- public void From$($baseUnit.PluralName)_WithNanValue_ThrowsArgumentException()
- {
- Assert.Throws(() => $quantityName.From$($baseUnit.PluralName)(double.NaN));
- }
-"@; }@"
-
- [Fact]
- public void As()
- {
- var $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance($($unit.PluralName)InOne$($baseUnit.SingularName), $baseUnitVariableName.As($($quantityName)Unit.$($unit.SingularName)), $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
- [Fact]
- public void ToUnit()
- {
- var $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units)
-{
- $asQuantityVariableName = "$($unit.SingularName.ToLowerInvariant())Quantity";
-@"
-
- var $asQuantityVariableName = $baseUnitVariableName.ToUnit($($quantityName)Unit.$($unit.SingularName));
- AssertEx.EqualTolerance($($unit.PluralName)InOne$($baseUnit.SingularName), (double)$asQuantityVariableName.Value, $($unit.PluralName)Tolerance);
- Assert.Equal($($quantityName)Unit.$($unit.SingularName), $asQuantityVariableName.Unit);
-"@; }@"
- }
-
- [Fact]
- public void ConversionRoundTrip()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
-"@; foreach ($unit in $units) {@"
- AssertEx.EqualTolerance(1, $quantityName.From$($unit.PluralName)($baseUnitVariableName.$($unit.PluralName)).$baseUnitPluralName, $($unit.PluralName)Tolerance);
-"@; }@"
- }
-
-"@; if ($quantity.Logarithmic -eq $true) {@"
- [Fact]
- public void LogarithmicArithmeticOperators()
- {
- $quantityName v = $quantityName.From$baseUnitPluralName(40);
- AssertEx.EqualTolerance(-40, -v.$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertLogarithmicAddition();
- AssertLogarithmicSubtraction();
- AssertEx.EqualTolerance(50, (v*10).$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertEx.EqualTolerance(50, (10*v).$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertEx.EqualTolerance(35, (v/5).$baseUnitPluralName, $($unit.PluralName)Tolerance);
- AssertEx.EqualTolerance(35, v/$quantityName.From$baseUnitPluralName(5), $($unit.PluralName)Tolerance);
- }
-
- protected abstract void AssertLogarithmicAddition();
-
- protected abstract void AssertLogarithmicSubtraction();
-
-"@; }
- elseif ($quantity.GenerateArithmetic -eq $true) {@"
- [Fact]
- public void ArithmeticOperators()
- {
- $quantityName v = $quantityName.From$baseUnitPluralName(1);
- AssertEx.EqualTolerance(-1, -v.$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, ($quantityName.From$baseUnitPluralName(3)-v).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, (v + v).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(10, (v*10).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(10, (10*v).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, ($quantityName.From$baseUnitPluralName(10)/5).$baseUnitPluralName, $($baseUnit.PluralName)Tolerance);
- AssertEx.EqualTolerance(2, $quantityName.From$baseUnitPluralName(10)/$quantityName.From$baseUnitPluralName(5), $($baseUnit.PluralName)Tolerance);
- }
-"@; }@"
-
- [Fact]
- public void ComparisonOperators()
- {
- $quantityName one$($baseUnit.SingularName) = $quantityName.From$baseUnitPluralName(1);
- $quantityName two$baseUnitPluralName = $quantityName.From$baseUnitPluralName(2);
-
- Assert.True(one$($baseUnit.SingularName) < two$baseUnitPluralName);
- Assert.True(one$($baseUnit.SingularName) <= two$baseUnitPluralName);
- Assert.True(two$baseUnitPluralName > one$($baseUnit.SingularName));
- Assert.True(two$baseUnitPluralName >= one$($baseUnit.SingularName));
-
- Assert.False(one$($baseUnit.SingularName) > two$baseUnitPluralName);
- Assert.False(one$($baseUnit.SingularName) >= two$baseUnitPluralName);
- Assert.False(two$baseUnitPluralName < one$($baseUnit.SingularName));
- Assert.False(two$baseUnitPluralName <= one$($baseUnit.SingularName));
- }
-
- [Fact]
- public void CompareToIsImplemented()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.Equal(0, $baseUnitVariableName.CompareTo($baseUnitVariableName));
- Assert.True($baseUnitVariableName.CompareTo($quantityName.Zero) > 0);
- Assert.True($quantityName.Zero.CompareTo($baseUnitVariableName) < 0);
- }
-
- [Fact]
- public void CompareToThrowsOnTypeMismatch()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.Throws(() => $baseUnitVariableName.CompareTo(new object()));
- }
-
- [Fact]
- public void CompareToThrowsOnNull()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.Throws(() => $baseUnitVariableName.CompareTo(null));
- }
-
- [Fact]
- public void EqualityOperators()
- {
- var a = $quantityName.From$baseUnitPluralName(1);
- var b = $quantityName.From$baseUnitPluralName(2);
-
- // ReSharper disable EqualExpressionComparison
-
- Assert.True(a == a);
- Assert.False(a != a);
-
- Assert.True(a != b);
- Assert.False(a == b);
-
- Assert.False(a == null);
- Assert.False(null == a);
-
-// ReSharper restore EqualExpressionComparison
- }
-
- [Fact]
- public void EqualsIsImplemented()
- {
- var a = $quantityName.From$baseUnitPluralName(1);
- var b = $quantityName.From$baseUnitPluralName(2);
-
- Assert.True(a.Equals(a));
- Assert.False(a.Equals(b));
- Assert.False(a.Equals(null));
- }
-
- [Fact]
- public void EqualsRelativeToleranceIsImplemented()
- {
- var v = $quantityName.From$baseUnitPluralName(1);
- Assert.True(v.Equals($quantityName.From$baseUnitPluralName(1), $($baseUnitPluralName)Tolerance, ComparisonType.Relative));
- Assert.False(v.Equals($quantityName.Zero, $($baseUnitPluralName)Tolerance, ComparisonType.Relative));
- }
-
- [Fact]
- public void EqualsReturnsFalseOnTypeMismatch()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.False($baseUnitVariableName.Equals(new object()));
- }
-
- [Fact]
- public void EqualsReturnsFalseOnNull()
- {
- $quantityName $baseUnitVariableName = $quantityName.From$baseUnitPluralName(1);
- Assert.False($baseUnitVariableName.Equals(null));
- }
-
- [Fact]
- public void UnitsDoesNotContainUndefined()
- {
- Assert.DoesNotContain($unitEnumName.Undefined, $quantityName.Units);
- }
-
- [Fact]
- public void HasAtLeastOneAbbreviationSpecified()
- {
- var units = Enum.GetValues(typeof($unitEnumName)).Cast<$unitEnumName>();
- foreach(var unit in units)
- {
- if(unit == $unitEnumName.Undefined)
- continue;
-
- var defaultAbbreviation = UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit);
- }
- }
-
- [Fact]
- public void BaseDimensionsShouldNeverBeNull()
- {
- Assert.False($quantityName.BaseDimensions is null);
- }
- }
-}
-"@;
-}
diff --git a/UnitsNet/Scripts/Include-GenerateUnitTestPlaceholderSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateUnitTestPlaceholderSourceCode.ps1
deleted file mode 100644
index 055b2bfc8e..0000000000
--- a/UnitsNet/Scripts/Include-GenerateUnitTestPlaceholderSourceCode.ps1
+++ /dev/null
@@ -1,37 +0,0 @@
-function GenerateUnitTestPlaceholderSourceCode($quantity)
-{
- $quantityName = $quantity.Name;
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated (once) by \generate-code.bat, but will not be
-// regenerated when it already exists. The purpose of creating this file is to make
-// it easier to remember to implement all the unit conversion test cases.
-//
-// Whenever a new unit is added to this quantity and \generate-code.bat is run,
-// the base test class will get a new abstract property and cause a compile error
-// in this derived class, reminding the developer to implement the test case
-// for the new unit.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-using System;
-
-namespace UnitsNet.Tests.CustomCode
-{
- public class $($quantityName)Tests : $($quantityName)TestsBase
- {
- // Override properties in base class here
- }
-}
-"@;
-}
diff --git a/UnitsNet/Scripts/Include-GenerateUnitTypeSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateUnitTypeSourceCode.ps1
deleted file mode 100644
index 047f218560..0000000000
--- a/UnitsNet/Scripts/Include-GenerateUnitTypeSourceCode.ps1
+++ /dev/null
@@ -1,56 +0,0 @@
-function GenerateUnitTypeSourceCode($quantity) {
- $quantityName = $quantity.Name;
- $units = $quantity.Units;
- $unitEnumName = "$($quantityName)Unit";
-@"
-//------------------------------------------------------------------------------
-//
-// This code was generated by \generate-code.bat.
-//
-// Changes to this file will be lost when the code is regenerated.
-// The build server regenerates the code before each build and a pre-build
-// step will regenerate the code on each local build.
-//
-// See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
-//
-// Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
-// Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
-//
-//
-//------------------------------------------------------------------------------
-
-// Licensed under MIT No Attribution, see LICENSE file at the root.
-// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
-
-// ReSharper disable once CheckNamespace
-namespace UnitsNet.Units
-{
- // Disable missing XML comment warnings for the generated unit enums.
- #pragma warning disable 1591
-
- public enum $unitEnumName
- {
- Undefined = 0,
-"@; foreach ($unit in $units) {
- $obsoleteAttribute = GetObsoleteAttribute($unit);
-
- if ($unit.XmlDocSummary) {@"
-
- ///
- /// $($unit.XmlDocSummary)
- ///
-"@; }
- if ($unit.XmlDocRemarks) {@"
- /// $($unit.XmlDocRemarks)
-"@; }
- if ($obsoleteAttribute) {@"
- $($obsoleteAttribute)
-"@; }@"
- $($unit.SingularName),
-"@; }@"
- }
-
- #pragma warning restore 1591
-}
-"@;
-}
diff --git a/UnitsNet/Scripts/Types.psm1 b/UnitsNet/Scripts/Types.psm1
deleted file mode 100644
index c94c9c2caa..0000000000
--- a/UnitsNet/Scripts/Types.psm1
+++ /dev/null
@@ -1,62 +0,0 @@
-class Quantity
-{
- [string]$Name
- [string]$XmlDocSummary
- [string]$XmlDocRemarks
- [string]$BaseUnit
- [string]$BaseType # TODO Rename me to ValueType
- [BaseDimensions]$BaseDimensions = [BaseDimensions]::new()
- [boolean]$GenerateArithmetic = $true
- [boolean]$Logarithmic = $false
- [int]$LogarithmicScalingFactor = 1
- [Unit[]]$Units = @()
-}
-
-class Unit
-{
- [string]$SingularName
- [string]$PluralName
- [string]$XmlDocSummary
- [string]$XmlDocRemarks
- [BaseUnits]$BaseUnits
- [string]$FromUnitToBaseFunc
- [string]$FromBaseToUnitFunc
- [string[]]$Prefixes = @()
- [Localization[]]$Localization = @()
-}
-
-class BaseUnits
-{
- [string]$Length
- [string]$Mass
- [string]$Time
- [string]$ElectricCurrent
- [string]$Temperature
- [string]$AmountOfSubstance
- [string]$LuminousIntensity
-}
-
-class Localization
-{
- [string]$Culture
- [string[]]$Abbreviations = @()
- [object[]]$AbbreviationsWithPrefixes = @()
-}
-
-class BaseDimensions
-{
- [int]$Length = 0
- [int]$Mass = 0
- [int]$Time = 0
- [int]$ElectricCurrent = 0
- [int]$Temperature = 0
- [int]$AmountOfSubstance = 0
- [int]$LuminousIntensity = 0
-}
-
-class GeneratorArgs
-{
- [Quantity]$Quantity
- [Unit]$BaseUnit
- [string]$UnitEnumName
-}
diff --git a/after.UnitsNet.sln.targets b/after.UnitsNet.sln.targets
deleted file mode 100644
index 7af52e24a9..0000000000
--- a/after.UnitsNet.sln.targets
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/generate-code.bat b/generate-code.bat
index 226a73d0da..26f3ccc04a 100644
--- a/generate-code.bat
+++ b/generate-code.bat
@@ -1,4 +1,3 @@
@echo off
SET scriptdir=%~dp0
-powershell -ExecutionPolicy Bypass -NoProfile -File "%scriptdir%UnitsNet/Scripts/GenerateUnits.ps1"
-powershell -ExecutionPolicy Bypass -NoProfile -File "%scriptdir%UnitsNet.WindowsRuntimeComponent./Scripts/GenerateUnits.ps1"
+dotnet run --project "%scriptdir%/CodeGen"