-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(generator): add constructor-based mapping support #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I stopped my review after my comment. Let's discuss.
ncipollina
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥 Love this solution. One comment to address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ Why did you add this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This how you made it work with dotnet test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes!
Co-authored-by: Nick Cipollina <[email protected]>
…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.
ncipollina
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀 Ship it!
- 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.
ncipollina
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ LGTM!
🚀 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: