Open sandboxFocusImprove this doc

LAMA0261: A declaration can have only one template or advice attribute

Severity Error
Reported by Metalama.Framework
Message Only one template or advice attribute is allowed on a declaration, the member it overrides, and its containing property or event, but '<Attribute>' is applied to '<Declaration>' and '<OtherAttribute>' is applied to '<OtherDeclaration>'.

Cause

Attributes such as TemplateAttribute and IntroduceAttribute mark a member of an aspect as a template and tell Metalama how to use it. An advice attribute like [Introduce] already makes the member a template, so the two can't be combined.

Metalama reports LAMA0261 when it finds more than one such attribute for the same member. It considers the attributes of the member itself and also:

  • the attributes of the member it overrides, for instance the [Template] attribute of OverrideMethodAspect.OverrideMethod;
  • for an accessor, the attributes of the containing property or event.

In the message, <Declaration> and <OtherDeclaration> are the declarations that carry the attributes <Attribute> and <OtherAttribute>.

The diagnostic is reported even if the aspect file doesn't import the Metalama.Framework namespaces with a using directive.

In the following example, the OverrideMethod method of the Log aspect has the [Template] attribute, although the method it overrides, OverrideMethodAspect.OverrideMethod, already has it.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0261.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    // Error: the base method is already a template, so [Template] is redundant.
9    [Template]
    Error LAMA0261: Only one template or advice attribute is allowed on a declaration, the member it overrides, and its containing property or event, but 'TemplateAttribute' is applied to 'LogAttribute.OverrideMethod()' and 'TemplateAttribute' is applied to 'OverrideMethodAspect.OverrideMethod()'.

10    public override dynamic? OverrideMethod()
11    {
12        Console.WriteLine( $"Executing {meta.Target.Method}." );
13
14        return meta.Proceed();
15    }
16}
17
1namespace Doc.LAMA0261.Error;
2
3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Keep only one attribute:

  • When you override a template method of a base class, such as OverrideMethod, don't add a template or advice attribute to the override: it inherits the attribute of the base method, as in the following example.
  • To introduce a member into the target type, use [Introduce] alone, without [Template].
  • To use a member as a template that you pass to an advice method, use [Template] alone, without an advice attribute.
  • Don't add an attribute to an accessor if the containing property or event already has one.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0261.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    // Fixed: the override inherits the [Template] attribute of the base method.
9    public override dynamic? OverrideMethod()
10    {
11        Console.WriteLine( $"Executing {meta.Target.Method}." );
12
13        return meta.Proceed();
14    }
15}
16
Source Code
1namespace Doc.LAMA0261.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.LAMA0261.Fixed;
4
5internal class Calculator
6{
7    [Log]
8    public int Add(int a, int b)
9    {
10        Console.WriteLine("Executing Calculator.Add(int, int).");
11        return a + b;
12    }
13}
14

See also