| Severity | Error |
| Reported by | Metalama.Extensions.Interceptors |
| Message | The <Site> is intercepted by more than one interceptor: <Sources>. At most one interceptor can apply to a call site. |
Cause
Metalama.Extensions.Interceptors lets aspects and fabrics replace the calls to selected methods with calls to other methods. A call can be replaced only once, so at most one interceptor can apply to a given call.
Metalama evaluates every registration whose scope and selection contain the call. A registration can decline the call, for instance with Skip in a ForEachSite delegate. Metalama reports LAMA1010 when more than one registration returns an interceptor instead of declining. It doesn't matter whether the registrations come from different aspects, from an aspect and a fabric, from several instances of the same aspect, or from the same fabric. In that case, Metalama doesn't intercept the call.
In the message, <Site> describes the call, and <Sources> lists the aspects and fabrics whose registrations returned an interceptor.
In the following example, a fabric registers two interceptors for the calls to Printer.Print.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Code;
3using Metalama.Framework.Fabrics;
4using System;
5using System.Linq;
6
7namespace Doc.LAMA1010.Error;
8
9internal class Fabric : ProjectFabric
10{
11 public override void AmendProject( IProjectAmender amender )
12 {
13 amender.InterceptMethods(
14 b => b
15 .Type( typeof(Printer) )
16 .Methods( "Print" )
17 .RedirectToExistingMethod( typeof(Interceptors).AsINamedType().Methods.OfName( "Log" ).Single() ) );
18
19 // Error: this second registration returns an interceptor for the same call.
20 amender.InterceptMethods(
21 b => b
22 .Type( typeof(Printer) )
23 .Methods( "Print" )
24 .RedirectToExistingMethod( typeof(Interceptors).AsINamedType().Methods.OfName( "Trace" ).Single() ) );
25 }
26}
27
28internal static class Interceptors
29{
30 public static void Log( string value ) => Console.WriteLine( "log: " + value );
31
32 public static void Trace( string value ) => Console.WriteLine( "trace: " + value );
33}
34
1using System;
2
3namespace Doc.LAMA1010.Error;
4
5internal static class Printer
6{
7 public static void Print( string value ) => Console.WriteLine( value );
8}
9
10internal static class Program
11{
Error LAMA1010: The call to 'Printer.Print(string)' is intercepted by more than one interceptor: the interceptor method 'Interceptors.Log(string)' registered by the fabric Doc.LAMA1010.Error.Fabric, the interceptor method 'Interceptors.Trace(string)' registered by the fabric Doc.LAMA1010.Error.Fabric. At most one interceptor can apply to a call site.
12 public static void Run() => Printer.Print( "Hello" );
13}
14
Resolution
Make sure that a single registration intercepts each call:
- Remove one of the registrations, or merge them into one interceptor. The following example keeps a single registration.
- Narrow the scope of the registrations, so that they no longer overlap.
- In a
ForEachSitedelegate, returnSkipfor the calls that another registration must handle.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Code;
3using Metalama.Framework.Fabrics;
4using System;
5using System.Linq;
6
7namespace Doc.LAMA1010.Fixed;
8
9internal class Fabric : ProjectFabric
10{
11 public override void AmendProject( IProjectAmender amender )
12 {
13 // A single registration returns an interceptor for the call.
14 amender.InterceptMethods(
15 b => b
16 .Type( typeof(Printer) )
17 .Methods( "Print" )
18 .RedirectToExistingMethod( typeof(Interceptors).AsINamedType().Methods.OfName( "Log" ).Single() ) );
19 }
20}
21
22internal static class Interceptors
23{
24 public static void Log( string value ) => Console.WriteLine( "log: " + value );
25
26 public static void Trace( string value ) => Console.WriteLine( "trace: " + value );
27}
28
1using System;
2
3namespace Doc.LAMA1010.Fixed;
4
5internal static class Printer
6{
7 public static void Print( string value ) => Console.WriteLine( value );
8}
9
10internal static class Program
11{
12 public static void Run() => Printer.Print( "Hello" );
13}
14
1using System;
2
3namespace Doc.LAMA1010.Fixed;
4
5internal static class Printer
6{
7 public static void Print(string value) => Console.WriteLine(value);
8}
9
10internal static class Program
11{
12 public static void Run() => Interceptors.Log("Hello");
13}
14