Skip to content

XP One nuget per quantity - #1181

Closed
angularsen wants to merge 2 commits into
masterfrom
agl/split-nuget-v5
Closed

XP One nuget per quantity#1181
angularsen wants to merge 2 commits into
masterfrom
agl/split-nuget-v5

Conversation

@angularsen

@angularsenangularsen commented Jan 7, 2023

Copy link
Copy Markdown
Owner

Related to #372, #1180

Experiment with splitting up UnitsNet nuget into:

  • UnitsNet.Core (common types and abstractions)
  • UnitsNet.Length
  • UnitsNet.Mass
  • etc..

This is already done for UnitsNet.nanoFramework nugets:
https://www.nuget.org/packages?q=unitsnet.nanoframework

We might also provide meta nuget packages that bring in multiple nugets in a single package:

  • UnitsNet (all nugets, like today)
  • UnitsNet.Meta.SI (all SI and SI derived nugets, such as Length, Force, Mass, Area, Speed etc)
  • UnitsNet.Meta.Main (the most widely used nugets, striving for 80/20 rule)

Benefits

  • Smaller size, only bring the quantities you need. The UnitsNet.dll is ~2MB as of 2023-01-07.
  • More extensible, it forces a design where plugging in 3rd party quantities is simpler.

Problems

  • QuantityType enum must be replaced by strings and using QuantityInfo instead
  • UnitSystem and BaseUnits rely on the 7 SI quantities Length, Mass, etc.
  • Arithmetic across quantities may not be feasible for the library to provide, such as Speed = Length / Duration and Mass.FromGravitationalForce(Force f). We might be able to provide this with meta nuget packages that bring in the most common quantities and arithmetic/conversions between them.

Design proposal

  • Use reflection to look up all quantities in loaded assemblies at startup instead of hard coding it, to allow plugging in 3rd party quantities. Need to provide some configuration for assemblies to search or quantities to load.
  • Make use of QuantityInfo to fully describe a quantity, instead of relying on generated code for known quantities spread over various types.
    • Unit abbreviations for different cultures, currently loaded by UnitAbbreviationsCache.LoadGeneratedAbbreviations() based on generated code.
    • Unit conversion functions, currently defined by generated code in Acceleration.RegisterDefaultConversions and similar for other quantities.

TEMP Remove all but 7 SI quantities
Add Duration and Length projects
TEMP Remove non-SI unit definitions
Add UnitsNet.SI, move SI stuff there
Include the 8 quantity projects in solution
@stale

staleBot commented Jun 18, 2023

Copy link
Copy Markdown

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stalestaleBot added the wontfix label Jun 18, 2023
@angularsenangularsen added the pinned Issues that should not be auto-closed due to inactivity. label Jul 14, 2023
@stalestaleBot removed the wontfix label Jul 14, 2023
@angularsen

Copy link
Copy Markdown
OwnerAuthor

test comment

@angularsen

Copy link
Copy Markdown
OwnerAuthor

test 2

@angularsen

Copy link
Copy Markdown
OwnerAuthor

test 3

@angularsenangularsen added pending-response Waiting for response from author of PR/issue. and removed wait-for-author labels Jul 16, 2023
@angularsen

Copy link
Copy Markdown
OwnerAuthor

test 4

@angularsen

Copy link
Copy Markdown
OwnerAuthor

test 5

@github-actionsgithub-actionsBot removed the pending-response Waiting for response from author of PR/issue. label Jul 16, 2023
@angularsenangularsen mentioned this pull request Sep 16, 2023
28 tasks
angularsen added a commit that referenced this pull request Jul 30, 2026
## Motivation
Explore a source-generated UnitsNet architecture where consumers
generate only the built-in and custom quantities they need while
retaining strongly typed quantities and units, parsing, conversion,
formatting, localization, and quantity relationships.
This is inspired by #902 and the ideas explored in #1181.
## Architecture
The primary model is consumer-owned generation:
- an application owns one generated units assembly and shares those CLR
types across its projects;
- `UnitsNet.Modular` supplies the runtime, source generator, authoring
contracts, and built-in catalog recipes;
- built-in recipes generate quantities in `UnitsNet` and unit enums in
`UnitsNet.Units` by default, preserving familiar consumer source;
- custom definitions retain their declared namespaces, while
`[UnitsNetModule("...")]` can explicitly place every selected definition
in another namespace;
- third parties normally ship definition packages containing public
markers, JSON definitions, localizations, conversion expressions, and
relationships rather than precompiled quantity structs;
- conversion metadata is immutable and generated at compile time; the
generated registry supports dynamic discovery without becoming mutable
global policy.
The POC introduces `UnitsNet.Core` for lean shared contracts, but
deliberately leaves the existing `UnitsNet` project and package
unchanged. Optional adoption by UnitsNet remains isolated on the stacked
`agl/unitsnetgen-poc-unitsnet-integration` branch.
## What this includes
- full built-in catalog selection plus named profiles, individual
additions, glob filters, and regex filters;
- custom UnitsNet-style JSON quantities, localizations, affine/nonlinear
conversion functions, and structured relationship files;
- generated linear, affine, and logarithmic quantities with typed
conversion, parsing, formatting, aggregation, operators, and selected
compatibility augmentations;
- immutable generated quantity registry and trimming/Native-AOT-friendly
System.Text.Json support;
- consumer-owned, project-reference, local-NuGet,
custom-definition-package, compatibility, lean, representative, and
all-SI samples;
- consumer-facing README with quick start, project structures, usage
examples, and full configuration details;
- Rider-friendly direct `AdditionalFiles` flow while retaining
`UnitsNetDefinition` and `UnitsNetRelation` item aliases for future
reference;
- separate `UnitsNet.Modular CI` workflow covering build, tests,
isolated NuGet consumption, Native AOT, deterministic packaging,
symbols, and Source Link;
- independent 6.x alpha MinVer streams using `UnitsNet.Modular/` and
`UnitsNet.Core/` tag prefixes, so their minor and patch versions can
advance independently.
## Review hardening
- synchronized with the current `QuantityValue`-based UnitsNet catalog
while retaining intentional `double` storage in this POC;
- validates C# identifiers and duplicate unit names as generator
diagnostics;
- composes prefixes inside the original conversion function, including
affine/nonlinear definitions;
- diagnoses unknown relation quantity IDs instead of silently dropping
recipes;
- consolidates unit-system and localized unit resolution through shared
operations;
- keeps full-catalog compatibility tests tracking `UnitsNet/**` changes
intentionally.
## Repository-level footprint
The standalone prototype also adds small shared-repository plumbing:
`Artifacts/Nugets/.gitkeep`, matching `.gitignore` rules, a
repository-local source in `nuget.config`, the
`RepositoryLocalNuGetFeed` property in `Directory.Build.props`, central
package versions in `Directory.Packages.props`, and local-feed cleanup
support in `Build/build-functions.psm1` and `Build/clean.ps1`. These
make local package output discoverable on a clean checkout and are not
consumer-facing package requirements.
## Deliberate boundaries
- Binary compatibility between generated structs and `UnitsNet.dll` is
not promised; source compatibility for common concrete APIs is the
target.
- Mutable `UnitsNetSetup`-style runtime conversion configuration is not
reproduced.
- Specialized feet/inches parsing and pressure/elevation modeling remain
explicit, tested exclusions.
- Configurable numeric storage types remain outside this PR so that
experiment can be reviewed independently.
## Validation
- Release restore and build of `UnitsNet.Modular.slnx`
- 108 tests passed: 35 runtime, 30 generator, and 43 full-catalog
compatibility tests
- local NuGet flow packed matching `UnitsNet.Modular` and
`UnitsNet.Core` packages
- publish-style packages produced as matching `6.0.0-alpha.0.<height>`
packages with symbols and the expected Core dependency
- Linux CI additionally runs the isolated NuGet consumer and Native AOT
smoke test
The local build reports two existing obsolete-quantity warnings from
generated legacy UnitsNet code and no errors.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pinnedIssues that should not be auto-closed due to inactivity.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@angularsen