| Severity | Error |
| Reported by | Metalama.Framework |
| Message | Cannot serialize the compile-time value of type '<Type>' to a run-time value because it contains a cyclic reference or is nested more than 32 levels deep. |
Cause
When a template uses a compile-time value in a run-time context, Metalama generates C# code that creates an equivalent value at run time. For a collection, it generates a collection initializer and converts each item recursively. A value that references itself, directly or through other collections, can't be expressed as a C# expression.
Metalama doesn't track the objects it has already converted. Instead, it reports LAMA0201 when the conversion goes deeper than 32 levels of nesting, so a value that's nested very deeply without any cycle also causes this error. Metalama reports the error when it expands the template, on the target declaration of the aspect. In the message, <Type> is the static type of the nested value being converted, which is often Object for an item of a collection.
In the following example, a compile-time list of tags accidentally contains itself. The list is assigned to an object variable because Metalama would otherwise reject the List<object> type when it compiles the template, with LAMA0200.
1using Metalama.Framework.Aspects;
2using System.Collections.Generic;
3
4namespace Doc.LAMA0201.Error;
5
6public class TagsAttribute : TypeAspect
7{
8 // Introduces a method that returns tags computed at compile time.
9 [Introduce]
10 public object GetTags()
11 {
12 var tags = meta.CompileTime( new List<object>() );
13 tags.Add( meta.Target.Type.Name );
14
15 // Error: the list contains itself, so it can't be converted to a run-time value.
16 tags.Add( tags );
17
18 // The value is typed as object, so Metalama converts it when it expands the template.
19 object result = tags;
20
21 return meta.RunTime( result );
22 }
23}
24
1namespace Doc.LAMA0201.Error;
2
3[Tags]
Error LAMA0201: Cannot serialize the compile-time value of type 'Object' to a run-time value because it contains a cyclic reference or is nested more than 32 levels deep.
4public partial class Customer
5{
6 public string? Name { get; set; }
7}
8
Resolution
Remove the cyclic reference from the compile-time value, or flatten a structure that's nested more than 32 levels deep. If the data is a graph, convert it to a structure without cycles before you use it in run-time code, for instance a list of nodes and a list of edges that identify the nodes by name.
In the following example, the list no longer contains itself.
1using Metalama.Framework.Aspects;
2using System.Collections.Generic;
3
4namespace Doc.LAMA0201.Fixed;
5
6public class TagsAttribute : TypeAspect
7{
8 // Introduces a method that returns tags computed at compile time.
9 [Introduce]
10 public object GetTags()
11 {
12 var tags = meta.CompileTime( new List<object>() );
13 tags.Add( meta.Target.Type.Name );
14
15 // Fixed: the list no longer contains itself.
16 tags.Add( meta.Target.Type.FullName );
17
18 // The value is typed as object, so Metalama converts it when it expands the template.
19 object result = tags;
20
21 return meta.RunTime( result );
22 }
23}
24
1namespace Doc.LAMA0201.Fixed;
2
3[Tags]
4public partial class Customer
5{
6 public string? Name { get; set; }
7}
8
1using System.Collections.Generic;
2
3namespace Doc.LAMA0201.Fixed;
4
5[Tags]
6public partial class Customer
7{
8 public string? Name { get; set; }
9
10 public object GetTags()
11 {
12 return new List<object>
13 {
14 "Customer",
15 "Doc.LAMA0201.Fixed.Customer"
16 };
17 }
18}
19