| 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:
- a template attribute, that is, an attribute that marks a member as a template or as a member to introduce, such as TemplateAttribute or IntroduceAttribute;
- a scope attribute, such as CompileTimeAttribute or [RunTime].
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