You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
✨ Add Quantity.From/TryFrom quantity name and unit name (#1258)
Make it easier to construct quantities from strings describing the
quantity name and unit name, if the unit enum value is not readily
available.
This is useful for custom serialization of quantities, such as mapping
to simple custom quantity DTO types instead of relying on JSON
serialization converters.
### Changes
- Add `Quantity.From` and `TryFrom`
- Refactor `UnitConverter` to reuse code for constructing quantity from
strings
- Add tests for `From` and `TryFrom`
- Add test `CustomSerializationTests.CanMapToJsonAndBackViaCustomDto` to
showcase serialization
### Example
```cs
public record QuantityDto(double Value, string QuantityName, string UnitName);
// The original quantity.
IQuantity q = Length.FromCentimeters(5);
// Map to DTO.
QuantityDto dto = new(
Value: (double)q.Value,
QuantityName: q.QuantityInfo.Name,
UnitName: q.Unit.ToString());
/* Serialize to JSON:
{
"Value": 5,
"QuantityName": "Length",
"UnitName": "Centimeter"
}
*/
var json = System.Text.Json.JsonSerializer.Serialize(dto);
// Deserialize from JSON.
QuantityDto deserialized = System.Text.Json.JsonSerializer.Deserialize<QuantityDto>(json)!;
// Map to IQuantity.
Quantity.TryFrom(deserialized.Value, deserialized.QuantityName, deserialized.UnitName, out IQuantity? deserializedQuantity);
```
The culture for abbreviations defaults to Thread.CurrentCulture and falls back to US English if not defined. Thread.CurrentCulture affects number formatting unless a custom culture is specified. The relevant methods are:
88
87
@@ -122,7 +121,7 @@ Unfortunately there is no built-in way to avoid this, either you need to ensure
122
121
Example:
123
122
`Length.Parse("1 pt")` throws `AmbiguousUnitParseException` with message `Cannot parse "pt" since it could be either of these: DtpPoint, PrinterPoint`.
124
123
125
-
### <aname="dynamic-parsing"></a>Dynamically Parse Quantities and Convert to Units
124
+
### Dynamically Parse Quantities and Convert to Units
126
125
Sometimes you need to work with quantities and units at runtime, such as parsing user input.
127
126
128
127
There are a handful of classes to help with this:
@@ -169,6 +168,16 @@ if (Quantity.TryFrom(3, LengthUnit.Centimeter, out IQuantity quantity2))
169
168
{
170
169
}
171
170
```
171
+
172
+
You can also construct from strings, such as mapping between DTO types in an API:
- [AddingaNewUnit](https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit) is fairly easy to do and we are happy to help.
324
329
-Wantanewfeatureortoreportabug? [Createanissue](https://github.com/angularsen/UnitsNet/issues/new/choose) or start a [discussion](https://github.com/angularsen/UnitsNet/discussions).
325
330
326
-
### <a name="ci"></a>Continuous Integration
331
+
### Continuous Integration
327
332
328
333
[AppVeyor](https://ci.appveyor.com/project/angularsen/unitsnet) performs the following:
### <a name="who-are-using"></a>Who are Using This?
338
+
### Who are Using This?
334
339
335
340
Itwouldbeawesometoknowwhoareusingthislibrary. Ifyouwouldlikeyourprojectlistedhere, [createanissue](https://github.com/angularsen/UnitsNet/issues) or edit the [README.md](https://github.com/angularsen/UnitsNet/edit/master/README.md) and send a pull request. Max logo size is `300x35 pixels` and should be in `.png`, `.gif` or `.jpg` formats.
Copy file name to clipboardExpand all lines: UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,7 @@ public abstract class UnitsNetBaseJsonConverter<T> : JsonConverter<T>
21
21
22
22
/// <summary>
23
23
/// Register custom types so that the converter can instantiate these quantities.
24
-
/// Instead of calling <see cref="Quantity.From"/>, the <see cref="Activator"/> will be used to instantiate the object.
24
+
/// Instead of calling <see cref="Quantity.From(UnitsNet.QuantityValue,System.Enum)"/>, the <see cref="Activator"/> will be used to instantiate the object.
25
25
/// It is therefore assumed that the constructor of <paramref name="quantity"/> is specified with <c>new T(double value, typeof(<paramref name="unit"/>) unit)</c>.
26
26
/// Registering the same <paramref name="unit"/> multiple times, it will overwrite the one registered.
:thrownewArgumentException($"Unit value {unit} of type {unit.GetType()} is not a known unit enum type. Expected types like UnitsNet.Units.LengthUnit. Did you pass in a third-party enum type defined outside UnitsNet library?");
67
+
}
66
68
67
-
thrownewArgumentException(
68
-
$"Unit value {unit} of type {unit.GetType()} is not a known unit enum type. Expected types like UnitsNet.Units.LengthUnit. Did you pass in a third-party enum type defined outside UnitsNet library?");
69
+
/// <summary>
70
+
/// Dynamically construct a quantity from a value, the quantity name and the unit name.
71
+
/// </summary>
72
+
/// <param name="value">Numeric value.</param>
73
+
/// <param name="quantityName">The invariant quantity name, such as "Length". Does not support localization.</param>
74
+
/// <param name="unitName">The invariant unit enum name, such as "Meter". Does not support localization.</param>
0 commit comments