| Severity | Error |
| Reported by | Metalama.Framework |
| Message | Cannot get a receiver in an advice applied to <TargetKind> '<TargetDeclaration>' because <Explanation>. |
Cause
In a template, meta.Receiver represents the object on which the target member is invoked: this in an instance member, or the receiver parameter in an extension member or a classic extension method. ExpressionFactory.Receiver returns the same expression as an IExpression.
A static member that isn't an extension method has no receiver. Metalama reports LAMA0287 when it expands a template that needs the receiver while the advice is applied to such a member, for instance a static method. The last part of the message explains why no receiver is available. Metalama detects the problem only when it expands the template for a given target, so the same aspect works on instance members and fails on static ones.
In the following example, the Trace aspect prints meta.Receiver. It works on the instance method Add, but fails on the static method Multiply.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0287.Error;
5
6public class TraceAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // meta.Receiver requires an instance member or an extension method.
11 Console.WriteLine( $"Executing {meta.Target.Method.Name} on {meta.Receiver}." );
12
13 return meta.Proceed();
14 }
15}
16
1namespace Doc.LAMA0287.Error;
2
3internal class Calculator
4{
5 private int _total;
6
7 [Trace]
8 public int Add( int value ) => this._total += value;
9
10 // Error: the template of [Trace] uses meta.Receiver, but this method is static.
11 [Trace]
Error LAMA0287: Cannot get a receiver in an advice applied to method 'Calculator.Multiply(int, int)' because the target method is static and is not an extension method.
12 public static int Multiply( int a, int b ) => a * b;
13}
14
Resolution
Depending on your intent, do one of the following:
- Make the template handle members without a receiver: call the HasReceiver extension method on the target member in a compile-time
ifstatement, and use meta.Receiver only in the branch where it returnstrue. The following example uses this approach. - If the aspect can't work without a receiver, add an eligibility condition to the aspect's BuildEligibility method, for instance MustNotBeStatic. Metalama then reports that the aspect isn't eligible on static members, and fabrics can skip them.
- Remove the aspect from the static member.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0287.Fixed;
6
7public class TraceAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 // Use meta.Receiver only when the target method has a receiver.
12 if ( meta.Target.Method.HasReceiver() )
13 {
14 Console.WriteLine( $"Executing {meta.Target.Method.Name} on {meta.Receiver}." );
15 }
16 else
17 {
18 Console.WriteLine( $"Executing {meta.Target.Method.Name}." );
19 }
20
21 return meta.Proceed();
22 }
23}
24
1namespace Doc.LAMA0287.Fixed;
2
3internal class Calculator
4{
5 private int _total;
6
7 [Trace]
8 public int Add( int value ) => this._total += value;
9
10 // Fixed: the template of [Trace] no longer uses meta.Receiver on methods without a receiver.
11 [Trace]
12 public static int Multiply( int a, int b ) => a * b;
13}
14
1using System;
2
3namespace Doc.LAMA0287.Fixed;
4
5internal class Calculator
6{
7 private int _total;
8
9 [Trace]
10 public int Add(int value)
11 {
12 Console.WriteLine($"Executing Add on {this}.");
13 return this._total += value;
14 }
15
16 // Fixed: the template of [Trace] no longer uses meta.Receiver on methods without a receiver.
17 [Trace]
18 public static int Multiply(int a, int b)
19 {
20 Console.WriteLine("Executing Multiply.");
21 return a * b;
22 }
23}
24