Open sandboxFocusImprove this doc

LAMA0269: An anonymous type is used in both run-time and compile-time code

Severity Error
Reported by Metalama.Framework
Message The anonymous type '<AnonymousType>' cannot be used in both run-time and compile-time code in the same template. Change the property names or types of one of the anonymous objects, or use a named type instead.

Cause

In a T# template, an anonymous object is normally run-time: Metalama copies the new { ... } expression into the target code. It's compile-time only when it appears in a compile-time context, for instance in the argument of meta.CompileTime(...) or in a lambda passed to a compile-time LINQ method.

The C# compiler gives the same anonymous type to all anonymous objects of a compilation that have the same property names, in the same order, with the same types. Metalama assigns a single scope to each anonymous type of a template, so it reports LAMA0269 when it finds the same anonymous type created once in run-time code and once in compile-time code. The <AnonymousType> placeholder shows the anonymous type, for instance <anonymous type: string Name>.

In the following example, the aspect creates a run-time anonymous object with a string property named Name, then a compile-time anonymous object with the same shape.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0269.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // This anonymous object is created at run time, in the target code.
11        var entry = new { Name = "Calculator" };
12        Console.WriteLine( entry );
13
14        // Error: the same anonymous type, with a single string property named Name, is created at compile time.
        Error LAMA0269: The anonymous type '<anonymous type: string Name>' cannot be used in both run-time and compile-time code in the same template. Change the property names or types of one of the anonymous objects, or use a named type instead.

15        var target = meta.CompileTime( new { Name = meta.Target.Method.Name } );
16
17        return meta.Proceed();
18    }
19}
20
1namespace Doc.LAMA0269.Error;
2
3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Make sure that the run-time and the compile-time anonymous objects have different anonymous types:

  • Rename a property of one of the anonymous objects, or change its type, as in the following example.
  • Use a named type instead of a compile-time anonymous object, for instance a class or a record marked with [CompileTime].

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0269.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // This anonymous object is created at run time, in the target code.
11        var entry = new { Name = "Calculator" };
12        Console.WriteLine( entry );
13
14        // Fixed: the compile-time anonymous object has a different property name, so it has a different anonymous type.
15        var target = meta.CompileTime( new { MethodName = meta.Target.Method.Name } );
16
17        return meta.Proceed();
18    }
19}
20
Source Code
1namespace Doc.LAMA0269.Fixed;
2


3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0269.Fixed;
4
5internal class Calculator
6{
7    [Log]
8    public int Add(int a, int b)
9    {
10        var entry = new
11        {
12            Name = "Calculator"
13        };
14        Console.WriteLine(entry);
15        return a + b;
16    }
17}
18

See also