Open sandboxFocusImprove this doc

LAMA0285: A local function in a template can't have a template or scope attribute

Severity Error
Reported by Metalama.Framework
Message The '<Attribute>' attribute is not allowed on a local function.

Cause

A template can contain local functions, but they're ordinary run-time code that's part of the template's body. Metalama doesn't let you change their role with attributes.

Metalama reports LAMA0285 when a local function declared in a template has one of the following attributes:

The <Attribute> placeholder is the name of the attribute type, for instance TemplateAttribute.

In the following example, the Log aspect tries to define an auxiliary template as a local function of its OverrideMethod template.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0285.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        LogEntry();
11
12        return meta.Proceed();
13
14        // Error: a local function can't be marked as a template.
        Error LAMA0285: The 'TemplateAttribute' attribute is not allowed on a local function.

15        [Template]
16        void LogEntry()
17        {
18            Console.WriteLine( $"Entering {meta.Target.Method.Name}." );
19        }
20    }
21}
22
1namespace Doc.LAMA0285.Error;
2
3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Depending on your intent, do one of the following:

  • To reuse a piece of template code, move the local function to a method of the aspect class, mark it with [Template], and call it from the template as an auxiliary template. The following example uses this approach.
  • To introduce a member, declare it as a member of the aspect class with [Introduce].
  • To run code at compile time, move it to a compile-time method of the aspect class.
  • If the local function is meant to be run-time code, remove the attribute.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0285.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        this.LogEntry();
11
12        return meta.Proceed();
13    }
14
15    // Fixed: the auxiliary template is a method of the aspect class.
16    [Template]
17    private void LogEntry()
18    {
19        Console.WriteLine( $"Entering {meta.Target.Method.Name}." );
20    }
21}
22
Source Code
1namespace Doc.LAMA0285.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.LAMA0285.Fixed;
4
5internal class Calculator
6{
7    [Log]
8    public int Add(int a, int b)
9    {
10        Console.WriteLine("Entering Add.");
11        return a + b;
12    }
13}
14

See also