| 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 System;
4
5namespace Doc.LAMA0210.Error;
6
7// Metalama cannot generate a serializer for a positional record.
8[RunTimeOrCompileTime]
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.
9public record RetryPolicy( int MaxAttempts ) : ICompileTimeSerializable;
10
11public class OrderService
12{
13 [Retry( 3 )]
14 public void PlaceOrder( int orderId )
15 {
16 Console.WriteLine( $"Placing order {orderId}." );
17 }
18}
19
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
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3using System;
4
5namespace Doc.LAMA0210.Fixed;
6
7[RunTimeOrCompileTime]
8public record RetryPolicy( int MaxAttempts ) : ICompileTimeSerializable
9{
10 // The record now provides its own serializer.
11 public class Serializer : ReferenceTypeSerializer<RetryPolicy>
12 {
13 public override RetryPolicy CreateInstance( IArgumentsReader constructorArguments )
14 => new( constructorArguments.GetValue<int>( "MaxAttempts" ) );
15
16 public override void SerializeObject( RetryPolicy obj, IArgumentsWriter constructorArguments, IArgumentsWriter initializationArguments )
17 => constructorArguments.SetValue( "MaxAttempts", obj.MaxAttempts );
18 }
19}
20
21public class OrderService
22{
23 [Retry( 3 )]
24 public void PlaceOrder( int orderId )
25 {
26 Console.WriteLine( $"Placing order {orderId}." );
27 }
28}
29
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3using System;
4
5namespace Doc.LAMA0210.Fixed;
6
7[RunTimeOrCompileTime]
8public record RetryPolicy(int MaxAttempts) : ICompileTimeSerializable
9{
10 // The record now provides its own serializer.
11
12#pragma warning disable CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
13
14
15 public class Serializer : ReferenceTypeSerializer<RetryPolicy>
16 {
17 public override RetryPolicy CreateInstance(IArgumentsReader constructorArguments) => throw new System.NotSupportedException("Compile-time-only code cannot be called at run-time.");
18
19
20 public override void SerializeObject(RetryPolicy obj, IArgumentsWriter constructorArguments, IArgumentsWriter initializationArguments) => throw new System.NotSupportedException("Compile-time-only code cannot be called at run-time.");
21 }
22
23#pragma warning restore CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
24
25
26}
27
28public class OrderService
29{
30 [Retry(3)]
31 public void PlaceOrder(int orderId)
32 {
33 for (var attempt = 1; ; attempt++)
34 {
35 try
36 {
37 Console.WriteLine($"Placing order {orderId}.");
38 return;
39 }
40 catch (Exception) when (attempt < 3)
41 {
42 Console.WriteLine($"Attempt {attempt} failed. Retrying.");
43 }
44 }
45 }
46}
47