Open sandboxFocusImprove this doc

LAMA0210: Metalama can't generate a serializer for a positional record

Severity Error
Reported by Metalama.Framework
Message Cannot generate a compile-time serializer for '<Type>' because generated serializers are not currently supported for a positional record class or struct. You can provide a manual serializer (public nested class) derived from ReferenceTypeSerializer (record classes) or ValueTypeSerializer (record structs) instead.

Cause

Metalama serializes aspects, fabrics, and other types implementing ICompileTimeSerializable when they have cross-project effects. By default, it generates a serializer for each of these types, unless the type declares its own nested serializer.

Metalama can't generate a serializer for a positional record, that is, a record, record class, or record struct declared with a parameter list. Metalama reports LAMA0210 when a positional record implements ICompileTimeSerializable, directly or through a base type, and doesn't declare a manual serializer. In the message, <Type> is the record.

In the following example, the RetryPolicy positional record implements ICompileTimeSerializable so that the Retry aspect can store it in a property.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0210.Error;
5
6public class RetryAttribute : OverrideMethodAspect
7{
8    public RetryAttribute( int maxAttempts )
9    {
10        this.Policy = new RetryPolicy( maxAttempts );
11    }
12
13    public RetryPolicy Policy { get; }
14
15    public override dynamic? OverrideMethod()
16    {
17        for ( var attempt = 1;; attempt++ )
18        {
19            try
20            {
21                return meta.Proceed();
22            }
23            catch ( Exception ) when ( attempt < this.Policy.MaxAttempts )
24            {
25                Console.WriteLine( $"Attempt {attempt} failed. Retrying." );
26            }
27        }
28    }
29}
30
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3using Metalama.Framework.Utilities;
4using System;
5
6namespace Doc.LAMA0210.Error;
7
8// Metalama cannot generate a serializer for a positional record.
9[RunTimeOrCompileTime]
10[ImmutableType]
Error LAMA0210: Cannot generate a compile-time serializer for 'RetryPolicy' because generated serializers are not currently supported for a positional record class or struct. You can provide a manual serializer (public nested class) derived from ReferenceTypeSerializer (record classes) or ValueTypeSerializer (record structs) instead.

11public record RetryPolicy( int MaxAttempts ) : ICompileTimeSerializable;
12
13public class OrderService
14{
15    [Retry( 3 )]
16    public void PlaceOrder( int orderId )
17    {
18        Console.WriteLine( $"Placing order {orderId}." );
19    }
20}
21

Resolution

Do one of the following:

  • Add a nested serializer class to the record: derive it from ReferenceTypeSerializer<T> for a record class or from ValueTypeSerializer<T> for a record struct. The following example shows this fix.
  • Declare the record without a parameter list, with ordinary properties instead of positional parameters. Metalama can generate serializers for such records.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0210.Fixed;
5
6public class RetryAttribute : OverrideMethodAspect
7{
8    public RetryAttribute( int maxAttempts )
9    {
10        this.Policy = new RetryPolicy( maxAttempts );
11    }
12
13    public RetryPolicy Policy { get; }
14
15    public override dynamic? OverrideMethod()
16    {
17        for ( var attempt = 1;; attempt++ )
18        {
19            try
20            {
21                return meta.Proceed();
22            }
23            catch ( Exception ) when ( attempt < this.Policy.MaxAttempts )
24            {
25                Console.WriteLine( $"Attempt {attempt} failed. Retrying." );
26            }
27        }
28    }
29}
30
Source Code
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3using Metalama.Framework.Utilities;
4using System;
5
6namespace Doc.LAMA0210.Fixed;
7
8[RunTimeOrCompileTime]
9[ImmutableType]
10public record RetryPolicy( int MaxAttempts ) : ICompileTimeSerializable
11{
12    // The record now provides its own serializer.
13    public class Serializer : ReferenceTypeSerializer<RetryPolicy>
14    {




15        public override RetryPolicy CreateInstance( IArgumentsReader constructorArguments )
16            => new( constructorArguments.GetValue<int>( "MaxAttempts" ) );
17
18        public override void SerializeObject( RetryPolicy obj, IArgumentsWriter constructorArguments, IArgumentsWriter initializationArguments )
19            => constructorArguments.SetValue( "MaxAttempts", obj.MaxAttempts );
20    }
21}
22




23public class OrderService
24{
25    [Retry( 3 )]
26    public void PlaceOrder( int orderId )







27    {
28        Console.WriteLine( $"Placing order {orderId}." );
29    }


30}


31
Transformed Code
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3using Metalama.Framework.Utilities;
4using System;
5
6namespace Doc.LAMA0210.Fixed;
7
8[RunTimeOrCompileTime]
9[ImmutableType]
10public record RetryPolicy(int MaxAttempts) : ICompileTimeSerializable
11{
12    // The record now provides its own serializer.
13
14#pragma warning disable CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
15
16
17    public class Serializer : ReferenceTypeSerializer<RetryPolicy>
18    {
19        public override RetryPolicy CreateInstance(IArgumentsReader constructorArguments) => throw new System.NotSupportedException("Compile-time-only code cannot be called at run-time.");
20
21
22        public override void SerializeObject(RetryPolicy obj, IArgumentsWriter constructorArguments, IArgumentsWriter initializationArguments) => throw new System.NotSupportedException("Compile-time-only code cannot be called at run-time.");
23    }
24

25#pragma warning restore CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
26
27
28}
29
30public class OrderService
31{
32    [Retry(3)]
33    public void PlaceOrder(int orderId)
34    {
35        for (var attempt = 1; ; attempt++)
36        {
37            try
38            {
39                Console.WriteLine($"Placing order {orderId}.");
40                return;
41            }
42            catch (Exception) when (attempt < 3)
43            {
44                Console.WriteLine($"Attempt {attempt} failed. Retrying.");
45            }
46        }
47    }
48}
49

See also