| 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
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
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