MemoryPack icon indicating copy to clipboard operation
MemoryPack copied to clipboard

[WIP] Add support for required and init-only properties

Open ardabada opened this issue 10 months ago • 0 comments

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 the required keyword, the source-generated code fails to initialize required properties, resulting in a CS9035 error.

Changes

  • Updated Object Instantiation for Circular Reference & Required Members

When deserializing types with circular references that include required members, the source generator now uses an uninitialized object rather than calling the default constructor.

id = reader.ReadVarIntUInt32();
if (value == null)
{
-    value = new Sample();
+    value = (Sample)global::System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Sample));
}
reader.OptionalState.AddObjectReference(id, value);

This ensures that an instance is created without triggering the constructor, thereby allowing the required members to be populated later during deserialization.

  • Handling Init-Only Properties

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 in PropertyHelper.SetInitOnlyProperty, as in AOT it's implemented via an interpreter. According to this Microsoft blog article, removing Expression.Compile() usage when in native AOT applications is recommended.

TODO

  • [ ] Ensure compatibility with [SuppressDefaultInitialization] attribute and default values
  • [ ] Ensure AOT compatibility

Related Issues

Fixes #370: Required members with circular reference causes CS9035.

ardabada avatar Feb 13 '25 19:02 ardabada