diff --git a/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs b/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs index f25cae0c6e..64479dbfa2 100644 --- a/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs +++ b/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs @@ -40,6 +40,17 @@ internal static class DefaultProvider {quantity.Name}.Info,"); Writer.WL(@" ]; + + internal static void RegisterUnitConversions(UnitConverter unitConverter) + {"); + foreach (Quantity quantity in _quantities) + { + Writer.WL($@" + {quantity.Name}.RegisterDefaultConversions(unitConverter);"); + } + + Writer.WL(@" + } } }"); return Writer.ToString(); diff --git a/PerfTests/PerfTest_Startup_Aot/PerfTest_Startup_Aot.csproj b/PerfTests/PerfTest_Startup_Aot/PerfTest_Startup_Aot.csproj new file mode 100644 index 0000000000..85893c202a --- /dev/null +++ b/PerfTests/PerfTest_Startup_Aot/PerfTest_Startup_Aot.csproj @@ -0,0 +1,17 @@ + + + + Exe + net9.0 + enable + enable + perftest + + true + + + + + + + diff --git a/PerfTests/PerfTest_Startup_Aot/Program.cs b/PerfTests/PerfTest_Startup_Aot/Program.cs new file mode 100644 index 0000000000..b54c226ab3 --- /dev/null +++ b/PerfTests/PerfTest_Startup_Aot/Program.cs @@ -0,0 +1,4 @@ +using UnitsNet; +using UnitsNet.Units; + +Console.WriteLine(Power.From(5, PowerUnit.Watt)); diff --git a/PerfTests/PerfTest_Startup_Aot/profile.sh b/PerfTests/PerfTest_Startup_Aot/profile.sh new file mode 100644 index 0000000000..1b145208f2 --- /dev/null +++ b/PerfTests/PerfTest_Startup_Aot/profile.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2155 +declare -r dirname=$(dirname -- "$0") + +pushd "$dirname" || exit +dotnet publish +dotnet timeit "$dirname/timeit.json" +popd || exit diff --git a/PerfTests/PerfTest_Startup_Aot/timeit.json b/PerfTests/PerfTest_Startup_Aot/timeit.json new file mode 100644 index 0000000000..13300ae3ad --- /dev/null +++ b/PerfTests/PerfTest_Startup_Aot/timeit.json @@ -0,0 +1,8 @@ +{ + "warmUpCount": 10, + "count": 20, + "scenarios": [{ "name": "Default" }], + "processName": "../../Artifacts/PerfTest_Startup_Aot/net9.0/win-x64/publish/PerfTest_Startup_Aot.exe", + "workingDirectory": "$(CWD)/", + "processTimeout": 15 +} diff --git a/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj b/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj index c384cfe943..26c9a5b99e 100644 --- a/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj +++ b/UnitsNet.NumberExtensions/UnitsNet.NumberExtensions.csproj @@ -27,6 +27,7 @@ enable UnitsNet netstandard2.0;net8.0;net9.0 + true diff --git a/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj b/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj index d7056c7332..c1ba0ba426 100644 --- a/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj +++ b/UnitsNet.Serialization.JsonNet/UnitsNet.Serialization.JsonNet.csproj @@ -28,6 +28,7 @@ enable UnitsNet.Serialization.JsonNet netstandard2.0;net8.0;net9.0 + true diff --git a/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs b/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs index 2ba1d5aead..73f4cce110 100644 --- a/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs +++ b/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Concurrent; -using System.Globalization; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -15,6 +15,10 @@ namespace UnitsNet.Serialization.JsonNet /// Contains shared functionality used by and /// /// The type being converted. Should either be or +#if NET + [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] + [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] +#endif public abstract class UnitsNetBaseJsonConverter : NullableQuantityConverter { private readonly ConcurrentDictionary _registeredTypes = new(); diff --git a/UnitsNet.Serialization.JsonNet/UnitsNetIComparableJsonConverter.cs b/UnitsNet.Serialization.JsonNet/UnitsNetIComparableJsonConverter.cs index 66445578f1..f1aa8b7618 100644 --- a/UnitsNet.Serialization.JsonNet/UnitsNetIComparableJsonConverter.cs +++ b/UnitsNet.Serialization.JsonNet/UnitsNetIComparableJsonConverter.cs @@ -2,6 +2,7 @@ // Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. using System; +using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -15,6 +16,10 @@ namespace UnitsNet.Serialization.JsonNet /// Should only be used when UnitsNet types are assigned to properties of type IComparable. /// Requires TypeNameHandling on to be set to something other than so that it outputs $type when serializing. /// +#if NET + [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] + [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] +#endif public sealed class UnitsNetIComparableJsonConverter : UnitsNetBaseJsonConverter { /// diff --git a/UnitsNet.Serialization.JsonNet/UnitsNetIQuantityJsonConverter.cs b/UnitsNet.Serialization.JsonNet/UnitsNetIQuantityJsonConverter.cs index d25ec17172..ceb76c6ecb 100644 --- a/UnitsNet.Serialization.JsonNet/UnitsNetIQuantityJsonConverter.cs +++ b/UnitsNet.Serialization.JsonNet/UnitsNetIQuantityJsonConverter.cs @@ -2,6 +2,7 @@ // Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. using System; +using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -12,6 +13,10 @@ namespace UnitsNet.Serialization.JsonNet /// JSON.net converter for IQuantity types (e.g. all units in UnitsNet) /// Use this converter to serialize and deserialize UnitsNet types to and from JSON /// +#if NET + [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] + [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] +#endif public sealed class UnitsNetIQuantityJsonConverter : UnitsNetBaseJsonConverter { /// diff --git a/UnitsNet.sln b/UnitsNet.sln index 878ab0a2d7..0b9f9fd6d0 100644 --- a/UnitsNet.sln +++ b/UnitsNet.sln @@ -70,6 +70,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PerfTests", "PerfTests", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerfTest_Startup_v4_72_0", "PerfTests\PerfTest_Startup_v4_72_0\PerfTest_Startup_v4_72_0.csproj", "{7131F7CC-BD7F-44EB-AD50-AE80CE38F28E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerfTest_Startup_Aot", "PerfTests\PerfTest_Startup_Aot\PerfTest_Startup_Aot.csproj", "{0222DB9C-52B5-4766-A068-617A44B7E3EB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -120,6 +122,10 @@ Global {7131F7CC-BD7F-44EB-AD50-AE80CE38F28E}.Debug|Any CPU.Build.0 = Debug|Any CPU {7131F7CC-BD7F-44EB-AD50-AE80CE38F28E}.Release|Any CPU.ActiveCfg = Release|Any CPU {7131F7CC-BD7F-44EB-AD50-AE80CE38F28E}.Release|Any CPU.Build.0 = Release|Any CPU + {0222DB9C-52B5-4766-A068-617A44B7E3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0222DB9C-52B5-4766-A068-617A44B7E3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0222DB9C-52B5-4766-A068-617A44B7E3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0222DB9C-52B5-4766-A068-617A44B7E3EB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -132,5 +138,6 @@ Global {BFF3DD22-0F58-4E79-86CD-662D1A174224} = {126F0393-A678-4609-9341-7028F1B2BC2B} {2E68C361-F6FA-49DC-BB0E-85ADE776391E} = {126F0393-A678-4609-9341-7028F1B2BC2B} {7131F7CC-BD7F-44EB-AD50-AE80CE38F28E} = {126F0393-A678-4609-9341-7028F1B2BC2B} + {0222DB9C-52B5-4766-A068-617A44B7E3EB} = {126F0393-A678-4609-9341-7028F1B2BC2B} EndGlobalSection EndGlobal diff --git a/UnitsNet/CustomCode/Wrappers/ReferencePressure.cs b/UnitsNet/CustomCode/Wrappers/ReferencePressure.cs index 5291b7d77b..5dec9517b0 100644 --- a/UnitsNet/CustomCode/Wrappers/ReferencePressure.cs +++ b/UnitsNet/CustomCode/Wrappers/ReferencePressure.cs @@ -2,8 +2,8 @@ // Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. using System; -using System.Linq; using UnitsNet.CustomCode.Units; +using UnitsNet.InternalHelpers; using UnitsNet.Units; namespace UnitsNet.Wrappers @@ -35,8 +35,7 @@ public struct ReferencePressure /// Gets a list of options: , /// , and /// - public static PressureReference[] References { get; } = - Enum.GetValues(typeof(PressureReference)).Cast().ToArray(); + public static PressureReference[] References { get; } = EnumHelper.GetValues(); /// /// Initializes a new instance of the struct requiring measured diff --git a/UnitsNet/GeneratedCode/Quantity.g.cs b/UnitsNet/GeneratedCode/Quantity.g.cs index fa85a9d164..c7a7c3af9c 100644 --- a/UnitsNet/GeneratedCode/Quantity.g.cs +++ b/UnitsNet/GeneratedCode/Quantity.g.cs @@ -165,5 +165,137 @@ internal static class DefaultProvider VolumetricHeatCapacity.Info, WarpingMomentOfInertia.Info, ]; + + internal static void RegisterUnitConversions(UnitConverter unitConverter) + { + AbsorbedDoseOfIonizingRadiation.RegisterDefaultConversions(unitConverter); + Acceleration.RegisterDefaultConversions(unitConverter); + AmountOfSubstance.RegisterDefaultConversions(unitConverter); + AmplitudeRatio.RegisterDefaultConversions(unitConverter); + Angle.RegisterDefaultConversions(unitConverter); + Area.RegisterDefaultConversions(unitConverter); + AreaDensity.RegisterDefaultConversions(unitConverter); + AreaMomentOfInertia.RegisterDefaultConversions(unitConverter); + BitRate.RegisterDefaultConversions(unitConverter); + BrakeSpecificFuelConsumption.RegisterDefaultConversions(unitConverter); + CoefficientOfThermalExpansion.RegisterDefaultConversions(unitConverter); + Compressibility.RegisterDefaultConversions(unitConverter); + Density.RegisterDefaultConversions(unitConverter); + DoseAreaProduct.RegisterDefaultConversions(unitConverter); + Duration.RegisterDefaultConversions(unitConverter); + DynamicViscosity.RegisterDefaultConversions(unitConverter); + ElectricAdmittance.RegisterDefaultConversions(unitConverter); + ElectricApparentEnergy.RegisterDefaultConversions(unitConverter); + ElectricApparentPower.RegisterDefaultConversions(unitConverter); + ElectricCapacitance.RegisterDefaultConversions(unitConverter); + ElectricCharge.RegisterDefaultConversions(unitConverter); + ElectricChargeDensity.RegisterDefaultConversions(unitConverter); + ElectricConductance.RegisterDefaultConversions(unitConverter); + ElectricConductivity.RegisterDefaultConversions(unitConverter); + ElectricCurrent.RegisterDefaultConversions(unitConverter); + ElectricCurrentDensity.RegisterDefaultConversions(unitConverter); + ElectricCurrentGradient.RegisterDefaultConversions(unitConverter); + ElectricField.RegisterDefaultConversions(unitConverter); + ElectricImpedance.RegisterDefaultConversions(unitConverter); + ElectricInductance.RegisterDefaultConversions(unitConverter); + ElectricPotential.RegisterDefaultConversions(unitConverter); + ElectricPotentialChangeRate.RegisterDefaultConversions(unitConverter); + ElectricReactance.RegisterDefaultConversions(unitConverter); + ElectricReactiveEnergy.RegisterDefaultConversions(unitConverter); + ElectricReactivePower.RegisterDefaultConversions(unitConverter); + ElectricResistance.RegisterDefaultConversions(unitConverter); + ElectricResistivity.RegisterDefaultConversions(unitConverter); + ElectricSurfaceChargeDensity.RegisterDefaultConversions(unitConverter); + ElectricSusceptance.RegisterDefaultConversions(unitConverter); + Energy.RegisterDefaultConversions(unitConverter); + EnergyDensity.RegisterDefaultConversions(unitConverter); + Entropy.RegisterDefaultConversions(unitConverter); + FluidResistance.RegisterDefaultConversions(unitConverter); + Force.RegisterDefaultConversions(unitConverter); + ForceChangeRate.RegisterDefaultConversions(unitConverter); + ForcePerLength.RegisterDefaultConversions(unitConverter); + Frequency.RegisterDefaultConversions(unitConverter); + FuelEfficiency.RegisterDefaultConversions(unitConverter); + HeatFlux.RegisterDefaultConversions(unitConverter); + HeatTransferCoefficient.RegisterDefaultConversions(unitConverter); + Illuminance.RegisterDefaultConversions(unitConverter); + Impulse.RegisterDefaultConversions(unitConverter); + Information.RegisterDefaultConversions(unitConverter); + Irradiance.RegisterDefaultConversions(unitConverter); + Irradiation.RegisterDefaultConversions(unitConverter); + Jerk.RegisterDefaultConversions(unitConverter); + KinematicViscosity.RegisterDefaultConversions(unitConverter); + LeakRate.RegisterDefaultConversions(unitConverter); + Length.RegisterDefaultConversions(unitConverter); + Level.RegisterDefaultConversions(unitConverter); + LinearDensity.RegisterDefaultConversions(unitConverter); + LinearPowerDensity.RegisterDefaultConversions(unitConverter); + Luminance.RegisterDefaultConversions(unitConverter); + Luminosity.RegisterDefaultConversions(unitConverter); + LuminousFlux.RegisterDefaultConversions(unitConverter); + LuminousIntensity.RegisterDefaultConversions(unitConverter); + MagneticField.RegisterDefaultConversions(unitConverter); + MagneticFlux.RegisterDefaultConversions(unitConverter); + Magnetization.RegisterDefaultConversions(unitConverter); + Mass.RegisterDefaultConversions(unitConverter); + MassConcentration.RegisterDefaultConversions(unitConverter); + MassFlow.RegisterDefaultConversions(unitConverter); + MassFlux.RegisterDefaultConversions(unitConverter); + MassFraction.RegisterDefaultConversions(unitConverter); + MassMomentOfInertia.RegisterDefaultConversions(unitConverter); + Molality.RegisterDefaultConversions(unitConverter); + MolarEnergy.RegisterDefaultConversions(unitConverter); + MolarEntropy.RegisterDefaultConversions(unitConverter); + MolarFlow.RegisterDefaultConversions(unitConverter); + Molarity.RegisterDefaultConversions(unitConverter); + MolarMass.RegisterDefaultConversions(unitConverter); + Permeability.RegisterDefaultConversions(unitConverter); + Permittivity.RegisterDefaultConversions(unitConverter); + PorousMediumPermeability.RegisterDefaultConversions(unitConverter); + Power.RegisterDefaultConversions(unitConverter); + PowerDensity.RegisterDefaultConversions(unitConverter); + PowerRatio.RegisterDefaultConversions(unitConverter); + Pressure.RegisterDefaultConversions(unitConverter); + PressureChangeRate.RegisterDefaultConversions(unitConverter); + RadiationEquivalentDose.RegisterDefaultConversions(unitConverter); + RadiationEquivalentDoseRate.RegisterDefaultConversions(unitConverter); + RadiationExposure.RegisterDefaultConversions(unitConverter); + Radioactivity.RegisterDefaultConversions(unitConverter); + Ratio.RegisterDefaultConversions(unitConverter); + RatioChangeRate.RegisterDefaultConversions(unitConverter); + ReciprocalArea.RegisterDefaultConversions(unitConverter); + ReciprocalLength.RegisterDefaultConversions(unitConverter); + RelativeHumidity.RegisterDefaultConversions(unitConverter); + RotationalAcceleration.RegisterDefaultConversions(unitConverter); + RotationalSpeed.RegisterDefaultConversions(unitConverter); + RotationalStiffness.RegisterDefaultConversions(unitConverter); + RotationalStiffnessPerLength.RegisterDefaultConversions(unitConverter); + Scalar.RegisterDefaultConversions(unitConverter); + SolidAngle.RegisterDefaultConversions(unitConverter); + SpecificEnergy.RegisterDefaultConversions(unitConverter); + SpecificEntropy.RegisterDefaultConversions(unitConverter); + SpecificFuelConsumption.RegisterDefaultConversions(unitConverter); + SpecificVolume.RegisterDefaultConversions(unitConverter); + SpecificWeight.RegisterDefaultConversions(unitConverter); + Speed.RegisterDefaultConversions(unitConverter); + StandardVolumeFlow.RegisterDefaultConversions(unitConverter); + Temperature.RegisterDefaultConversions(unitConverter); + TemperatureChangeRate.RegisterDefaultConversions(unitConverter); + TemperatureDelta.RegisterDefaultConversions(unitConverter); + TemperatureGradient.RegisterDefaultConversions(unitConverter); + ThermalConductivity.RegisterDefaultConversions(unitConverter); + ThermalInsulance.RegisterDefaultConversions(unitConverter); + ThermalResistance.RegisterDefaultConversions(unitConverter); + Torque.RegisterDefaultConversions(unitConverter); + Turbidity.RegisterDefaultConversions(unitConverter); + VitaminA.RegisterDefaultConversions(unitConverter); + Volume.RegisterDefaultConversions(unitConverter); + VolumeConcentration.RegisterDefaultConversions(unitConverter); + VolumeFlow.RegisterDefaultConversions(unitConverter); + VolumeFlowPerArea.RegisterDefaultConversions(unitConverter); + VolumePerLength.RegisterDefaultConversions(unitConverter); + VolumetricHeatCapacity.RegisterDefaultConversions(unitConverter); + WarpingMomentOfInertia.RegisterDefaultConversions(unitConverter); + } } } diff --git a/UnitsNet/InternalHelpers/EnumHelper.cs b/UnitsNet/InternalHelpers/EnumHelper.cs new file mode 100644 index 0000000000..13c7bbe7c1 --- /dev/null +++ b/UnitsNet/InternalHelpers/EnumHelper.cs @@ -0,0 +1,26 @@ +// 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. + +#if !NET7_0_OR_GREATER +using System.Linq; +#endif + +namespace UnitsNet.InternalHelpers; + +/// +/// Helper methods for working with types. +/// +internal static class EnumHelper +{ + /// Retrieves an array of the values of the constants in a specified enumeration type. + /// The type of the enumeration. + /// An array that contains the values of the constants in . + public static TEnum[] GetValues() where TEnum : struct, Enum + { +#if NET7_0_OR_GREATER + return Enum.GetValues(); +#else + return Enum.GetValues(typeof(TEnum)).Cast().ToArray(); +#endif + } +} diff --git a/UnitsNet/QuantityTypeConverter.cs b/UnitsNet/QuantityTypeConverter.cs index 7722b87623..eb98248e31 100644 --- a/UnitsNet/QuantityTypeConverter.cs +++ b/UnitsNet/QuantityTypeConverter.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace UnitsNet @@ -138,7 +139,12 @@ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type source return (sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType); } - private static TAttribute? GetAttribute(ITypeDescriptorContext? context) where TAttribute : UnitAttributeBase + private static TAttribute? GetAttribute< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + TAttribute + >(ITypeDescriptorContext? context) where TAttribute : UnitAttributeBase { if (context?.PropertyDescriptor is null) return null; diff --git a/UnitsNet/UnitConverter.cs b/UnitsNet/UnitConverter.cs index 0a9b75df11..6d6d8ab43f 100644 --- a/UnitsNet/UnitConverter.cs +++ b/UnitsNet/UnitConverter.cs @@ -1,12 +1,8 @@ // 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.Concurrent; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; using UnitsNet.InternalHelpers; -using UnitsNet.Units; namespace UnitsNet { @@ -80,16 +76,11 @@ private ConcurrentDictionary Co /// Registers the default conversion functions in the given instance. /// /// The to register the default conversion functions in. - public static void RegisterDefaultConversions(UnitConverter unitConverter) + private static void RegisterDefaultConversions(UnitConverter unitConverter) { - if (unitConverter is null) - throw new ArgumentNullException(nameof(unitConverter)); + if (unitConverter is null) throw new ArgumentNullException(nameof(unitConverter)); - foreach (var quantity in Quantity.DefaultProvider.Quantities) - { - var registerMethod = quantity.QuantityType.GetMethod(nameof(Length.RegisterDefaultConversions), BindingFlags.NonPublic | BindingFlags.Static); - registerMethod?.Invoke(null, new object[]{unitConverter}); - } + Quantity.DefaultProvider.RegisterUnitConversions(unitConverter); } /// diff --git a/UnitsNet/UnitsNet.csproj b/UnitsNet/UnitsNet.csproj index 3814bf6d39..ed8231ba47 100644 --- a/UnitsNet/UnitsNet.csproj +++ b/UnitsNet/UnitsNet.csproj @@ -28,6 +28,7 @@ enable UnitsNet netstandard2.0;net8.0;net9.0 + true