Skip to content

Commit bd4282f

Browse files
lipchevangularsen
andauthored
QuantityFormatter: Take UnitAbbreviationsCache instance, Format with TQuantity (#1551)
- `QuantityFormatter`: introducing an `UnitAbbreviationsCache` instance and `Format`-ing using a generic `TQuantity` - `UnitsNetSetup`: introduced an instance property for the `UnitFormatter` - `IQuantity`: added the `UnitKey` property (implemented explicitly) - replaced the existing usages of the `QuantityFormatter` and marked the static `Format` overloads as `[Obsolete]` fixes #1447 --------- Co-authored-by: Andreas Gullberg Larsen <andreas.larsen84@gmail.com>
1 parent d2fb4b4 commit bd4282f

File tree

144 files changed

+2312
-1965
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

144 files changed

+2312
-1965
lines changed

CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs

+16-14
Original file line numberDiff line numberDiff line change
@@ -290,25 +290,30 @@ private void GenerateProperties()
290290
/// </summary>
291291
public double Value => _value;
292292
293-
/// <inheritdoc />
294-
double IQuantity.Value => _value;
295-
296-
Enum IQuantity.Unit => Unit;
297-
298293
/// <inheritdoc />
299294
public {_unitEnumName} Unit => _unit.GetValueOrDefault(BaseUnit);
300295
301296
/// <inheritdoc />
302297
public QuantityInfo<{_unitEnumName}> QuantityInfo => Info;
303298
304-
/// <inheritdoc cref=""IQuantity.QuantityInfo""/>
305-
QuantityInfo IQuantity.QuantityInfo => Info;
306-
307299
/// <summary>
308300
/// The <see cref=""BaseDimensions"" /> of this quantity.
309301
/// </summary>
310302
public BaseDimensions Dimensions => {_quantity.Name}.BaseDimensions;
311303
304+
#region Explicit implementations
305+
306+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
307+
Enum IQuantity.Unit => Unit;
308+
309+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
310+
UnitKey IQuantity.UnitKey => UnitKey.ForUnit(Unit);
311+
312+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
313+
QuantityInfo IQuantity.QuantityInfo => Info;
314+
315+
#endregion
316+
312317
#endregion
313318
");
314319
}
@@ -1167,7 +1172,7 @@ public string ToString(IFormatProvider? provider)
11671172
return ToString(null, provider);
11681173
}}
11691174
1170-
/// <inheritdoc cref=""QuantityFormatter.Format{{TUnitType}}(IQuantity{{TUnitType}}, string, IFormatProvider)""/>
1175+
/// <inheritdoc cref=""QuantityFormatter.Format{{TQuantity}}(TQuantity, string?, IFormatProvider?)""/>
11711176
/// <summary>
11721177
/// Gets the string representation of this instance in the specified format string using <see cref=""CultureInfo.CurrentCulture"" />.
11731178
/// </summary>
@@ -1178,16 +1183,13 @@ public string ToString(string? format)
11781183
return ToString(format, null);
11791184
}}
11801185
1181-
/// <inheritdoc cref=""QuantityFormatter.Format{{TUnitType}}(IQuantity{{TUnitType}}, string, IFormatProvider)""/>
1186+
/// <inheritdoc cref=""QuantityFormatter.Format{{TQuantity}}(TQuantity, string?, IFormatProvider?)""/>
11821187
/// <summary>
11831188
/// Gets the string representation of this instance in the specified format string using the specified format provider, or <see cref=""CultureInfo.CurrentCulture"" /> if null.
11841189
/// </summary>
1185-
/// <param name=""format"">The format string.</param>
1186-
/// <param name=""provider"">Format to use for localization and number formatting. Defaults to <see cref=""CultureInfo.CurrentCulture"" /> if null.</param>
1187-
/// <returns>The string representation.</returns>
11881190
public string ToString(string? format, IFormatProvider? provider)
11891191
{{
1190-
return QuantityFormatter.Format<{_unitEnumName}>(this, format, provider);
1192+
return QuantityFormatter.Default.Format(this, format, provider);
11911193
}}
11921194
11931195
#endregion

UnitsNet.Benchmark/Conversions/ToString/ToStringWithDefaultPrecisionBenchmarks.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace UnitsNet.Benchmark.Conversions.ToString;
99

1010
[MemoryDiagnoser]
1111
[SimpleJob(RuntimeMoniker.Net48)]
12-
[SimpleJob(RuntimeMoniker.Net80)]
12+
[SimpleJob(RuntimeMoniker.Net90)]
1313
public class ToStringWithDefaultPrecisionBenchmarks
1414
{
1515
private static readonly double Value = 123.456;

UnitsNet.Benchmark/Enums/UnitKeyEqualsBenchmarks.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ public class UnitKeyEqualsBenchmarks
1616

1717
private static readonly UnitKey UnitKey = UnitKey.ForUnit(VolumeUnit.CubicMeter);
1818
private static readonly UnitKey OtherUnitKey = UnitKey.ForUnit(VolumeUnit.AcreFoot);
19-
private readonly Type OtherUnitType = UnitKey.UnitType;
20-
private readonly int OtherUnitValue = UnitKey.UnitValue;
19+
private readonly Type OtherUnitType = UnitKey.UnitEnumType;
20+
private readonly int OtherUnitValue = UnitKey.UnitEnumValue;
2121

22-
private readonly Type UnitType = UnitKey.UnitType;
23-
private readonly int UnitValue = UnitKey.UnitValue;
22+
private readonly Type UnitType = UnitKey.UnitEnumType;
23+
private readonly int UnitValue = UnitKey.UnitEnumValue;
2424

2525
[Benchmark(Baseline = true)]
2626
public bool EqualsRecord()

UnitsNet.Benchmark/Enums/UnitKeyHashCodeBenchmarks.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public class UnitKeyHashCodeBenchmarks
1717

1818
private static readonly UnitKey UnitKey = UnitKey.ForUnit(VolumeUnit.CubicMeter);
1919

20-
private readonly Type UnitType = UnitKey.UnitType;
21-
private readonly int UnitValue = UnitKey.UnitValue;
20+
private readonly Type UnitType = UnitKey.UnitEnumType;
21+
private readonly int UnitValue = UnitKey.UnitEnumValue;
2222

2323
[Benchmark(Baseline = true)]
2424
public int GetHashCodeRecord()

UnitsNet.Benchmark/Enums/UnitKeyToEnumBenchmarks.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public int ManualCast()
2323
var total = 0;
2424
for (var i = 0; i < NbIterations; i++)
2525
{
26-
if ((MassUnit)unitKey.UnitValue == MassUnit.Gram)
26+
if ((MassUnit)unitKey.UnitEnumValue == MassUnit.Gram)
2727
{
2828
total++;
2929
}

UnitsNet.Tests/CustomQuantities/HowMuch.cs

+5
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ QuantityInfo IQuantity.QuantityInfo
4949
{
5050
get { return Info; }
5151
}
52+
53+
public UnitKey UnitKey
54+
{
55+
get => UnitKey.ForUnit(Unit);
56+
}
5257

5358
public double As(Enum unit) => Convert.ToDouble(unit);
5459

UnitsNet.Tests/DummyIQuantity.cs

-34
This file was deleted.

UnitsNet.Tests/QuantityFormatterTests.cs

+26-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Globalization;
6+
using UnitsNet.Tests.Helpers;
67
using Xunit;
78

89
namespace UnitsNet.Tests
@@ -95,9 +96,9 @@ public static void StandardNumericFormatStrings_Equals_ValueWithFormatStringAndA
9596
var length = Length.FromMeters(123456789.987654321);
9697

9798
var expected = string.Format(CultureInfo.CurrentCulture, $"{{0:{format}}} {{1:a}}", length.Value, length);
98-
Assert.Equal(expected, QuantityFormatter.Format(length, format));
99+
Assert.Equal(expected, QuantityFormatter.Default.Format(length, format));
99100
}
100-
101+
101102
[Theory]
102103
[InlineData("U")]
103104
[InlineData("u")]
@@ -140,9 +141,9 @@ public static void StandardNumericFormatStrings_Equals_ValueWithFormatStringAndA
140141
public static void Format_WithUnsupportedFormatString_ThrowsFormatException(string format)
141142
{
142143
var length = Length.FromMeters(123456789.987654321);
143-
Assert.Throws<FormatException>(() => QuantityFormatter.Format(length, format));
144+
Assert.Throws<FormatException>(() => QuantityFormatter.Default.Format(length, format));
144145
}
145-
146+
146147
[Fact]
147148
public static void StandardNumericFormatStringsAsPartOfLongerFormatStringsWork()
148149
{
@@ -173,7 +174,27 @@ public static void CustomNumericFormatStrings_Equals_ValueWithFormatStringAndAbb
173174
var length = Length.FromMeters(123456789.987654321);
174175

175176
var expected = string.Format(CultureInfo.CurrentCulture, $"{{0:{format}}} {{1:a}}", length.Value, length);
176-
Assert.Equal(expected, QuantityFormatter.Format(length, format));
177+
Assert.Equal(expected, QuantityFormatter.Default.Format(length, format));
178+
}
179+
180+
[Fact]
181+
public void Format_WithoutFormatParameter_FormatsWithGeneralFormatWithCurrentCulture()
182+
{
183+
using var cultureScope = new CultureScope(CultureInfo.InvariantCulture);
184+
var length = Length.FromMeters(123.321);
185+
var expected = "123.321 m";
186+
var actual = QuantityFormatter.Default.Format(length);
187+
Assert.Equal(expected, actual);
188+
}
189+
190+
[Fact]
191+
public void Format_WithFormatParameter_FormatsWithCurrentCulture()
192+
{
193+
using var cultureScope = new CultureScope(CultureInfo.InvariantCulture);
194+
var length = Length.FromMeters(123.321);
195+
var expected = "123.321 m";
196+
var actual = QuantityFormatter.Format(length, "G");
197+
Assert.Equal(expected, actual);
177198
}
178199
}
179200
}

UnitsNet.Tests/QuantityTest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public void TryFrom_GivenValueAndUnit_ReturnsQuantity()
180180
[Fact]
181181
public void TryParse_GivenInvalidQuantityType_ReturnsFalseAndNullQuantity()
182182
{
183-
Assert.False(Quantity.TryParse(InvariantCulture, typeof(DummyIQuantity), "3.0 cm", out IQuantity? parsedLength));
183+
Assert.False(Quantity.TryParse(InvariantCulture, typeof(DateTime), "3.0 cm", out IQuantity? parsedLength));
184184
Assert.Null(parsedLength);
185185
}
186186

UnitsNet.Tests/UnitAbbreviationsCacheTests.cs

+12
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ public void GetDefaultAbbreviationFallsBackToInvariantCulture()
126126
// Assert
127127
Assert.Equal("Invariant abbreviation for Unit1", abbreviation);
128128
}
129+
130+
[Fact]
131+
public void GetDefaultAbbreviation_WithNullUnitType_ThrowsArgumentNullException()
132+
{
133+
Assert.Throws<ArgumentNullException>(() => UnitAbbreviationsCache.Default.GetDefaultAbbreviation(null!, 1));
134+
}
129135

130136
[Fact]
131137
public void GetDefaultAbbreviationThrowsUnitNotFoundExceptionIfNoneExist()
@@ -149,6 +155,12 @@ public void GetAllUnitAbbreviationsForQuantity_WithQuantityWithoutAbbreviations_
149155
Assert.Empty(unitAbbreviationsCache.GetAllUnitAbbreviationsForQuantity(typeof(HowMuchUnit)));
150156
}
151157

158+
[Fact]
159+
public void GetAllUnitAbbreviationsForQuantity_WithNullUnitType_ThrowsArgumentNullException()
160+
{
161+
Assert.Throws<ArgumentNullException>(() => UnitAbbreviationsCache.Default.GetAllUnitAbbreviationsForQuantity(null!));
162+
}
163+
152164
[Fact]
153165
public void GetAllUnitAbbreviationsForQuantity_WithInvalidUnitType_ThrowsArgumentException()
154166
{

UnitsNet.Tests/UnitKeyTest.cs

+37-14
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ public enum TestUnit
2323
public void Constructor_ShouldCreateUnitKey(int unitValue)
2424
{
2525
var unitKey = new UnitKey(typeof(TestUnit), unitValue);
26-
Assert.Equal(typeof(TestUnit), unitKey.UnitType);
27-
Assert.Equal(unitValue, unitKey.UnitValue);
26+
Assert.Equal(typeof(TestUnit), unitKey.UnitEnumType);
27+
Assert.Equal(unitValue, unitKey.UnitEnumValue);
2828
}
2929

3030
[Fact]
3131
public void Constructor_WithNullType_ShouldNotThrow()
3232
{
3333
var unitKey = new UnitKey(null!, 0);
34-
Assert.Null(unitKey.UnitType);
35-
Assert.Equal(0, unitKey.UnitValue);
34+
Assert.Null(unitKey.UnitEnumType);
35+
Assert.Equal(0, unitKey.UnitEnumValue);
3636
}
3737

3838
[Theory]
@@ -42,8 +42,8 @@ public void Constructor_WithNullType_ShouldNotThrow()
4242
public void ForUnit_ShouldCreateUnitKey(TestUnit unit)
4343
{
4444
var unitKey = UnitKey.ForUnit(unit);
45-
Assert.Equal(typeof(TestUnit), unitKey.UnitType);
46-
Assert.Equal((int)unit, unitKey.UnitValue);
45+
Assert.Equal(typeof(TestUnit), unitKey.UnitEnumType);
46+
Assert.Equal((int)unit, unitKey.UnitEnumValue);
4747
}
4848

4949
[Theory]
@@ -53,8 +53,31 @@ public void ForUnit_ShouldCreateUnitKey(TestUnit unit)
5353
public void Create_ShouldCreateUnitKey(int unitValue)
5454
{
5555
var unitKey = UnitKey.Create<TestUnit>(unitValue);
56-
Assert.Equal(typeof(TestUnit), unitKey.UnitType);
57-
Assert.Equal(unitValue, unitKey.UnitValue);
56+
Assert.Equal(typeof(TestUnit), unitKey.UnitEnumType);
57+
Assert.Equal(unitValue, unitKey.UnitEnumValue);
58+
}
59+
60+
[Theory]
61+
[InlineData(typeof(TestUnit), 1)]
62+
[InlineData(typeof(TestUnit), 2)]
63+
[InlineData(typeof(TestUnit), 3)]
64+
public void Create_WithUnitTypeAndUnitValue_ShouldCreateUnitKey(Type unitType, int unitValue)
65+
{
66+
var unitKey = UnitKey.Create(unitType, unitValue);
67+
Assert.Equal(unitType, unitKey.UnitEnumType);
68+
Assert.Equal(unitValue, unitKey.UnitEnumValue);
69+
}
70+
71+
[Fact]
72+
public void Create_WithNullUnitType_ShouldThrowArgumentNullException()
73+
{
74+
Assert.Throws<ArgumentNullException>(() => UnitKey.Create(null!, 0));
75+
}
76+
77+
[Fact]
78+
public void Create_WithNonEnumType_ShouldThrowArgumentException()
79+
{
80+
Assert.Throws<ArgumentException>(() => UnitKey.Create(typeof(int), 1));
5881
}
5982

6083
[Theory]
@@ -64,8 +87,8 @@ public void Create_ShouldCreateUnitKey(int unitValue)
6487
public void ImplicitConversion_ShouldCreateUnitKey(TestUnit unit)
6588
{
6689
UnitKey unitKey = unit;
67-
Assert.Equal(typeof(TestUnit), unitKey.UnitType);
68-
Assert.Equal((int)unit, unitKey.UnitValue);
90+
Assert.Equal(typeof(TestUnit), unitKey.UnitEnumType);
91+
Assert.Equal((int)unit, unitKey.UnitEnumValue);
6992
}
7093

7194
[Theory]
@@ -94,8 +117,8 @@ public void ToUnit_ShouldReturnEnum(TestUnit unit)
94117
public void Default_InitializesWithoutAType()
95118
{
96119
var defaultUnitKey = default(UnitKey);
97-
Assert.Null(defaultUnitKey.UnitType);
98-
Assert.Equal(0, defaultUnitKey.UnitValue);
120+
Assert.Null(defaultUnitKey.UnitEnumType);
121+
Assert.Equal(0, defaultUnitKey.UnitEnumValue);
99122
}
100123

101124
[Fact]
@@ -139,7 +162,7 @@ public void Deconstruct_ShouldReturnTheUnitTypeAndUnitValue()
139162
[InlineData(TestUnit.Unit1, "TestUnit.Unit1")]
140163
[InlineData(TestUnit.Unit2, "TestUnit.Unit2")]
141164
[InlineData(TestUnit.Unit3, "TestUnit.Unit3")]
142-
[InlineData((TestUnit)(-1), "UnitType: UnitsNet.Tests.UnitKeyTest+TestUnit, UnitValue = -1")]
165+
[InlineData((TestUnit)(-1), "UnitEnumType: UnitsNet.Tests.UnitKeyTest+TestUnit, UnitEnumValue = -1")]
143166
public void GetDebuggerDisplay_ShouldReturnCorrectString(TestUnit unit, string expectedDisplay)
144167
{
145168
var unitKey = UnitKey.ForUnit(unit);
@@ -154,6 +177,6 @@ public void GetDebuggerDisplayWithDefault_ShouldReturnCorrectString()
154177
var defaultUnitKey = default(UnitKey);
155178
var display = defaultUnitKey.GetType().GetMethod("GetDebuggerDisplay", BindingFlags.NonPublic | BindingFlags.Instance)!
156179
.Invoke(defaultUnitKey, null);
157-
Assert.Equal("UnitType: , UnitValue = 0", display);
180+
Assert.Equal("UnitEnumType: , UnitEnumValue = 0", display);
158181
}
159182
}

0 commit comments

Comments
 (0)