fix(binder): bind nullable value-type properties over underlying type#161
Merged
Conversation
A nullable value-type DTO property (int?, bool?) inferred TArgument as Nullable<T>, so a value-object factory over the underlying type (int -> Outcome<T>) could not bind as a method group (CS0411). Add a struct-constrained SimpleProperty/ListOfSimpleProperties overload whose selector carries Nullable<TArgument>: structurally more specific than the reference overload, it wins for value-type properties and surfaces the underlying non-nullable type, while reference and string properties keep resolving to the original overload. Lists of value types get a dedicated converter that unwraps each present element and records a null element as a missing argument under its indexed path. Refs: #144
Record the public-API-contract decision behind the value-type selector overloads: a nullable value-type DTO property binds through a dedicated struct-constrained overload whose selector carries Nullable<TArgument> and whose converter runs over the underlying non-nullable type. Drafted as Proposed and indexed; the maintainer decides its status. Refs: #144
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
A nullable value-type DTO property (
int?,bool?) could not bind through a method-group converter over its underlying type — the call failed to compile withCS0411, becauseSimpleProperty(r => r.Prop)inferredTArgument = Nullable<int>and the converter stage then expectedFunc<Nullable<int>, Outcome<T>>. This adds struct-constrained selector overloads so such properties bind directly against anint-taking converter, and records the API-shape decision as ADR-0008 (Proposed).Type of change
Changes
where TArgument : structoverloads ofSimplePropertyandListOfSimpleProperties. Under the constraint,TArgument?is the constructedNullable<TArgument>— structurally more specific than the reference overload's bareTArgument— so the value-type overload wins for a nullable-value-type property and surfaces the underlying non-nullable type, with noCS0111/CS0121. Reference and string properties keep resolving to the original overloads.ListOfSimpleValuePropertiesConverter<TRequest, TArgument>: the value-type counterpart of the list converter — it unwraps each present element and records anullelement as a missing argument (REQUEST_ARGUMENT_REQUIRED) under its indexed path.AsOptionalValue, fallback,bool?, lists (required / null-element / invalid-element / optional-absent),string?andList<string?>regressions, and the non-nullableintguard.doc/RequestBinder.en.mdanddoc/RequestBinder.fr.md(lockstep).Proposed) recording the struct-constrained-overload decision, and index it.Testing
dotnet build FirstClassErrors.sln— succeeded, 0 warnings / 0 errors.dotnet test FirstClassErrors.sln— all green (Cli 63, Core 423, Analyzers 85, GenDoc 136, PropertyTests 21, RequestBinder 75), 0 failed.FirstClassErrors.Analyzers.UnitTests) — 85 passed (run as part of the full-solution suite above).The binder suite is 75 tests = 62 existing + 13 new; no regression.
Documentation
doc/updated — RequestBinder guide (EN).doc/RequestBinder.fr.mdwas updated in lockstep with the English guide;doc/README.fr.mditself needed no change.Architecture decisions
Proposed: ADR-0008ADR-0008 records the public-API-contract decision (the struct-constrained overload shape) surfaced by #144 as
architecture+blocking, gated on the v1 API freeze. Drafted asProposed; the maintainer decides its status.Related issues
Closes #144
🤖 Generated with Claude Code
Generated by Claude Code