Modernize UnifiedId: IParsable/ISpanParsable/IFormattable/ISpanFormattable + System.Text.Json - #24
Merged
Conversation
…rmattable + System.Text.Json Multi-target the core package (netstandard2.0;net8.0;net10.0) and implement the modern .NET parsing/formatting interfaces on net8.0+ so UnifiedId participates in generic parsing, ASP.NET Core model binding, allocation-free Span formatting, and can serve as the backing value for strongly-typed id libraries (e.g. StructId). - UnifiedId implements IParsable<UnifiedId>, ISpanParsable<UnifiedId>, IFormattable and ISpanFormattable (guarded by #if NET8_0_OR_GREATER). Hot paths (TryParse/TryFormat) are allocation-free; format/provider are accepted but ignored (single canonical 13-char HEX32 representation). - Align Equals/CompareTo(object?/string?) parameter nullability with the BCL interface contracts (metadata-only; surfaced by the net8+ targets). - New Unified.Text.Json package: UnifiedIdJsonConverter (JsonConverter<UnifiedId>) serializing the canonical HEX32 string, including dictionary-key support. - Tests: 12 new (modern interfaces + System.Text.Json); 42 total, all green. All changes are additive and non-breaking. Legacy ISerializable is retained (SYSLIB0050 suppressed); implicit->explicit operator tightening and EF Core/Dapper/TypeConverter integrations are intentionally left as follow-ups. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…on-blocking The single "Build and analyze" step wrapped build+test inside SonarCloud begin...end, so an expired/rejected SONAR_TOKEN (auth failure in `begin`) failed the whole job even though the build succeeded and all tests passed. - Split Build and Test into their own required steps (the hard gate). - Gate all SonarCloud steps on `env.SONAR_TOKEN != ''` and mark the analyze step `continue-on-error: true`, so credential/infra problems in the advisory analysis can never again fail an otherwise-green build (also unblocks fork PRs, which don't receive the secret). - SonarCloud still runs its own build between begin/end and reads the coverage reports produced by the Test step, so analysis is unchanged when the token is valid. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes
UnifiedIda first-class modern .NET identifier and a viable backing value for strongly-typed id libraries (e.g. devlooped/StructId, Vogen, StronglyTypedId), by adding the parsing/formatting interfaces those libraries and the BCL rely on, plus aSystem.Text.Jsonconverter.Everything here is additive and non-breaking (new interfaces + a new package; no existing signature/behavior changes).
What changed
netstandard2.0→netstandard2.0;net8.0;net10.0.netstandard2.0keeps its existing zero-dependencychar[]code path unchanged.net8.0+ (guarded by#if NET8_0_OR_GREATER):IParsable<UnifiedId>,ISpanParsable<UnifiedId>,IFormattable,ISpanFormattable.TryParse/TryFormat) are allocation-free (Span/stackalloc); the stringParseoverloads only allocate on the rare error path.format/providerare accepted but ignored —UnifiedIdhas a single canonical 13-char HEX32 representation. Empty/round-trip semantics preserved exactly.Equals(object?),Equals(string?),CompareTo(object?),CompareTo(string?)now match the BCL interface contracts. These mismatches were latent and only surface once the modern (annotated) reference assemblies are targeted; the change is metadata-only.Unified.Text.Jsonpackage (mirrors the existingUnified.Json/Newtonsoft package):UnifiedIdJsonConverter : JsonConverter<UnifiedId>serializing the canonical HEX32 string, includingWriteAsPropertyName/ReadAsPropertyNameso aUnifiedIdworks as a dictionary key.Testing
ModernInterfacesTests,SystemTextJsonTests) — including a genericwhere T : IParsable<T>call proving the constraint is satisfied, span/too-small-bufferTryFormat, interpolation viaISpanFormattable, and STJ round-trip + dictionary-key round-trip.TreatWarningsAsErrorson) acrossnetstandard2.0/net8.0/net10.0.dotnet packverified:Unifiedshipslib/netstandard2.0+lib/net8.0+lib/net10.0;Unified.Text.Jsondeclares itsUnified+System.Text.Jsondeps.Intentionally out of scope (follow-ups)
implicit→explicitconversion tightening (breaking; belongs to a major version).ValueConverter+ValueComparer, DapperTypeHandler,TypeConverter.ISerializablepath (kept as-is;SYSLIB0050suppressed on modern targets, matching the test project's existing convention).🤖 Generated with Claude Code