[WIP] Add support for required and init-only properties #374
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.
Overview
This PR fixes the compilation error CS9035 (required member must be set in the object initializer or attribute constructor) that occurs when using required members with circular reference serialization. In cases when
GenerateType.CircularReference
is used together with therequired
keyword, the source-generated code fails to initialize required properties, resulting in a CS9035 error.Changes
When deserializing types with circular references that include required members, the source generator now uses an uninitialized object rather than calling the default constructor.
This ensures that an instance is created without triggering the constructor, thereby allowing the required members to be populated later during deserialization.
For classes that contain init-only properties which must be set during deserialization, the generated code now leverages
PropertyHelper.SetInitOnlyProperty
to assign values. This helper method retrieves the property's setter via reflection, caches the delegate for performance, and then invokes the setter.SET: + global::MemoryPack.PropertyHelper.SetInitOnlyProperty<Sample, string>(value, nameof(Sample.SomeInitOnlyProperty), __SomeInitOnlyProperty); goto READ_END; NEW: value = new Sample() { @SomeInitOnlyProperty = __SomeInitOnlyProperty };
Expression.Lambda.Compile
method can be used inPropertyHelper.SetInitOnlyProperty
, as in AOT it's implemented via an interpreter. According to this Microsoft blog article, removingExpression.Compile()
usage when in native AOT applications is recommended.TODO
[SuppressDefaultInitialization]
attribute and default valuesRelated Issues
Fixes #370: Required members with circular reference causes CS9035.