Open sandboxFocusImprove this doc

LAMA1013: The interceptor method isn't compatible with the call site

Severity Error
Reported by Metalama.Extensions.Interceptors
Message The method '<Method>' cannot intercept the <Site> because <Reason>.

Cause

The Metalama.Extensions.Interceptors package lets an aspect or a fabric replace the calls to selected methods with calls to another method, called an interceptor. With RedirectToExistingMethod, the interceptor is a method that you've written. Metalama replaces the call with a call to this method, and the compiler must be able to bind the new call.

Metalama reports LAMA1013 when the method doesn't satisfy this requirement. In the message, <Method> is the proposed interceptor, <Site> describes the intercepted call, and <Reason> gives the incompatibility. The interceptor method must, among others:

  • be static;
  • be accessible from the call site;
  • have a signature that matches the intercepted method: the parameters, their types and ref, in and out modifiers, and the return type;
  • receive the receiver as its first parameter when the intercepted method is an instance method;
  • be a run-time method, not a compile-time method.

Metalama also reports LAMA1013 for a base call to a virtual method, because a static method would call the method with a virtual dispatch and reach the override.

In the following example, a fabric redirects the calls to PriceCalculator.ApplyDiscount to an instance method.

1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Code;
3using Metalama.Framework.Fabrics;
4using System.Linq;
5
6namespace Doc.LAMA1013.Error;
7
8internal class Fabric : ProjectFabric
9{
10    public override void AmendProject( IProjectAmender amender )
11    {
12        amender.SelectTypes()
13            .Where( t => t.Name == "Checkout" )
14            .InterceptMethods(
15                b => b
16                    .Type( typeof(PriceCalculator) )
17                    .Methods( "ApplyDiscount" )
18                    .RedirectToExistingMethod(
19                        typeof(DiscountedPriceCalculator).AsINamedType().Methods.OfName( "ApplyDiscount" ).Single() ) );
20    }
21}
22
1using System;
2
3namespace Doc.LAMA1013.Error;
4
5internal static class PriceCalculator
6{
7    public static decimal ApplyDiscount( decimal price ) => price * 0.9m;
8}
9
10internal class DiscountedPriceCalculator
11{
12    // The interceptor method must be static.
13    public decimal ApplyDiscount( decimal price ) => price * 0.8m;
14}
15
16internal static class Checkout
17{
    Error LAMA1013: The method 'DiscountedPriceCalculator.ApplyDiscount(decimal)' cannot intercept the call to 'PriceCalculator.ApplyDiscount(decimal)' because it is not static.

18    public static void Run() => Console.WriteLine( PriceCalculator.ApplyDiscount( 100m ) );
19}
20

Resolution

Fix the interceptor method according to the reason given in the message. In the following example, the interceptor method is made static.

Alternatively, use RedirectToSynthesizedMethod and let Metalama generate the interceptor method from a template: the signature is then derived from the intercepted method.

1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Code;
3using Metalama.Framework.Fabrics;
4using System.Linq;
5
6namespace Doc.LAMA1013.Fixed;
7
8internal class Fabric : ProjectFabric
9{
10    public override void AmendProject( IProjectAmender amender )
11    {
12        amender.SelectTypes()
13            .Where( t => t.Name == "Checkout" )
14            .InterceptMethods(
15                b => b
16                    .Type( typeof(PriceCalculator) )
17                    .Methods( "ApplyDiscount" )
18                    .RedirectToExistingMethod(
19                        typeof(DiscountedPriceCalculator).AsINamedType().Methods.OfName( "ApplyDiscount" ).Single() ) );
20    }
21}
22
Source Code
1using System;
2
3namespace Doc.LAMA1013.Fixed;
4
5internal static class PriceCalculator
6{
7    public static decimal ApplyDiscount( decimal price ) => price * 0.9m;
8}
9
10internal static class DiscountedPriceCalculator
11{
12    // The interceptor method is static.
13    public static decimal ApplyDiscount( decimal price ) => price * 0.8m;
14}
15
16internal static class Checkout
17{
18    public static void Run() => Console.WriteLine( PriceCalculator.ApplyDiscount( 100m ) );
19}
20
Transformed Code
1using System;
2
3namespace Doc.LAMA1013.Fixed;
4
5internal static class PriceCalculator
6{
7    public static decimal ApplyDiscount(decimal price) => price * 0.9m;
8}
9
10internal static class DiscountedPriceCalculator
11{
12    // The interceptor method is static.
13    public static decimal ApplyDiscount(decimal price) => price * 0.8m;
14}
15
16internal static class Checkout
17{
18    public static void Run() => Console.WriteLine(DiscountedPriceCalculator.ApplyDiscount(100m));
19}
20