feat(generator): add constructor-based mapping support#62
Merged
Conversation
…erialization - Introduced `DynamoMapperConstructorAttribute` to specify a constructor for DynamoDB deserialization. - Enables better control over deserialization in DynamoMapper.
- Added a new example project `DynamoMapper.MapperConstructor` to demonstrate constructor mapping. - Configured project dependencies for DynamoMapper runtime and generator. - Updated solution file to include the new example project.
- Added `RecordMapper` to map `PersonRecord` to and from DynamoDB items. - Added `ClassWithConstructor` to map `PersonClass` using a constructor for deserialization.
- Added tests for various class and record types with constructors or properties.
- Included scenarios like primary constructors, read-only properties, init-only properties,
and multiple constructors.
- Added failure cases for multiple attributed constructors.
- Ensures support for diverse constructor and property setups in DynamoMapper.
fix(diagnostics): add descriptor for multiple attributed constructors
- Introduced `DM0103` diagnostic descriptor for detecting multiple constructors marked with
`[DynamoMapperConstructor]`.
- Provides clear guidance to maintain a single attributed constructor per type.
…on methods - Added `ConstructorSelector` to determine suitable constructors for deserialization. - Introduced `InitializationMethod` to outline property initialization strategies during deserialization. - Implemented `PropertyInitializationMode` to support constructor and property-based mapping. - Enhanced property analysis with `MemberAnalyzer` for shared semantic logic. - Expanded `WellKnownTypeData` with `DynamoMapperConstructorAttribute`. This commit enables robust constructor-based deserialization in DynamoMapper.
…logic - Updated XML documentation to enhance clarity and consistency across multiple files. - Simplified conditional checks in `PropertyMappingCodeRenderer`. - Refactored `ConstructorSelector` with expanded multiline formatting for improved readability. - Applied minor naming adjustments and null checks where necessary. - Improved accessibility checks for property symbols in `AllPropertiesAccessible`. - Streamlined loop and conditional structures in `ModelClassInfo` and related files. This commit enhances code maintainability and improves readability without altering functionality.
… selection - Updated `AllPropertiesAccessible` to account for computed and read-only properties. - Improved constructor parameter matching for read-only properties during deserialization. - Refined logic to ignore computed properties that do not require construction population. - Expanded XML documentation for clear deserialization behavior guidelines. - Adjusted conditional logic to enhance clarity and deserialization accuracy.
…ML comments - Removed unused `<param>` XML comments in `PropertyMappingCodeRenderer` and `PropertyInfo`. - Corrected punctuation in diagnostic messages for consistency. - Added missing diagnostics to `AnalyzerReleases.Unshipped.md`.
- Added instructions for listing, filtering, and running tests for specific namespaces/classes. - Documented usage of xUnit v3 filtered test runs with Microsoft.Testing.Platform. - Included detailed examples for single test execution and method/class-level filters in `CLAUDE.md` and `AGENTS.md`.
…e initialization logic - Standardized punctuation for diagnostic `MessageFormat` across codebase and test snapshot files. - Adjusted comments in `ConstructorSelector` to clarify property initialization approach. - Enhanced initialization method logic to prefer object-initializer assignments for clarity and defaults.
…ection logic - Extracted property-related operations into dedicated methods for reusability and clarity. - Centralized constructor selection logic into a standalone method for improved maintainability. - Improved property analysis with modular functions for property initialization and diagnostics generation. - Enhanced readability and organization of `CreatePropertyInfos` and `CreateConstructorInfo`.
- Specified .NET SDK version as "10.0.101" for project consistency. - Added roll-forward policy set to "latestMinor" to allow minor version updates automatically.
ncipollina
requested changes
Jan 19, 2026
Contributor
ncipollina
left a comment
There was a problem hiding this comment.
I stopped my review after my comment. Let's discuss.
ncipollina
requested changes
Jan 19, 2026
Contributor
ncipollina
left a comment
There was a problem hiding this comment.
🔥 Love this solution. One comment to address.
Contributor
There was a problem hiding this comment.
❓ Why did you add this?
Collaborator
Author
There was a problem hiding this comment.
This was needed to make MTP tests work when run through the CLI. I added this along with the agent commands so that coding agents could better run tests without burning tokens.
Contributor
There was a problem hiding this comment.
This how you made it work with dotnet test?
Co-authored-by: Nick Cipollina <ncipollina@gmail.com>
…n in DynamoMapper - Added examples showcasing constructor-based deserialization in `index.md`. - Documented constructor selection rules for `FromItem` in `basic-mapping.md`. - Explained `[DynamoMapperConstructor]` usage in `attributes.md`. - Updated `how-it-works.md` with object construction approaches during deserialization. - Revised `phase-1.md` roadmap to include constructor-based deserialization support.
- Added detailed explanations for constructor mapping rules in `basic-mapping.md`. - Linked cross-references to constructor mapping rules from `attributes.md` and `how-it-works.md`. - Documented hybrid constructor and object initializer usage in `basic-mapping.md`. - Updated examples and added references for constructor-based deserialization scenarios.
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.
🚀 Pull Request
📋 Summary
This PR adds comprehensive support for constructor-based mapping in DynamoMapper, enabling the source generator to deserialize DynamoDB items into C# records and classes with parameterized constructors. This is a major enhancement that expands the types of domain models that can be used with DynamoMapper.
Key Features Added
Constructor-Based Deserialization: The generator now analyzes constructors and intelligently selects the best one for deserialization based on parameter-to-property matching.
[DynamoMapperConstructor]Attribute: Allows explicit constructor selection when multiple constructors are available.Primary Constructor Support: Full support for C# 12+ primary constructors on records and classes.
Init-Only Properties: Support for properties with
initaccessors that can only be set during object construction.Hybrid Initialization: Handles models that use both constructor parameters and settable properties, with smart property initialization mode detection.
Comprehensive Diagnostics: Added new compile-time diagnostics (DM0003-DM0007) to guide developers when constructor mapping issues are detected.
Changes by Component
Generator Enhancements:
ConstructorSelector: New component that analyzes and selects the best constructor for deserializationMemberAnalyzer: Shared logic for analyzing both properties and constructor parametersModelClassInfowith constructor metadata and initialization trackingFromItemmethodsRuntime API:
DynamoMapperConstructorAttributeto mark preferred constructorsTesting:
Documentation:
CLAUDE.mdandAGENTS.mdwith xUnit v3 test commandsDynamoMapper.MapperConstructorprojectTechnical Details
The constructor selection logic prioritizes:
[DynamoMapperConstructor]Property initialization modes are determined per-property:
ConstructorParameter: Property is set via constructor parameterDirectAssignment: Property is set after construction (regular orinitsetter)ReadOnly: Property is read-only and only set via constructor✅ Checklist
🧪 Related Issues or PRs
This PR implements a core Phase 1 feature for DynamoMapper, enabling it to work with a much broader range of domain models beyond simple POCOs with parameterless constructors.
💬 Notes for Reviewers
Areas to Focus On:
Constructor Selection Logic (
ConstructorSelector.cs): The algorithm for choosing the best constructor and matching parameters to properties. Pay attention to the name matching logic (exact, case-insensitive, underscore prefix handling).Property Initialization Modes: The logic in
ModelClassInfo.csthat determines whether each property should be set via constructor parameter or direct assignment.Template Changes (
Mapper.scriban): The newFromItemgeneration logic that handles constructor invocation with parameter mapping.Diagnostics: The new error messages (DM0003-DM0007) should be clear and actionable for developers.
Test Coverage: Review the snapshot tests in
ConstructorVerifyTests.csto ensure all edge cases are covered.Known Limitations:
Follow-up Work: