Open sandboxFocusImprove this doc

LAMA1001: The interception scope is not valid

Severity Error
Reported by Metalama.Extensions.Interceptors
Message The <Source> cannot use the <ScopeKind> '<Scope>' as an interception scope. A scope must be a namespace, a type, a member or the compilation, and it must be declared in the source code of the current project.

Cause

Metalama.Extensions.Interceptors lets an aspect or a fabric replace the calls to selected methods, in the source code of the current project, with calls to other methods. An aspect or fabric registers an interceptor with the InterceptMethods method of its adviser, builder, or amender. The declaration on which you call this method is the interception scope: only the calls located inside this declaration are intercepted.

A scope must be a namespace, a type, a member (method, constructor, property, indexer, field or event) or the compilation. Other declarations, such as parameters and type parameters, can't be scopes. The scope must also be declared in the source code of the current project, because Metalama can intercept only the calls that exist in this source code. A type from a referenced assembly, such as Console, can't be a scope.

Metalama reports LAMA1001 when a query or adviser returns a declaration that doesn't satisfy these rules. In the message, <Source> describes the aspect or fabric, <ScopeKind> is the kind of the declaration, and <Scope> is the declaration.

In the following example, the fabric registers the interceptor on the Console class, which belongs to a referenced assembly.

1using System;
2using System.Linq;
3using Metalama.Extensions.Interceptors;
4using Metalama.Framework.Code;
5using Metalama.Framework.Fabrics;
6
7namespace Doc.LAMA1001.Error;
8
Error LAMA1001: The interceptor method 'Logger.Write(string)' registered by the fabric Doc.LAMA1001.Error.Fabric cannot use the type 'Console' as an interception scope. A scope must be a namespace, a type, a member or the compilation, and it must be declared in the source code of the current project.

9public class Fabric : ProjectFabric
10{
11    public override void AmendProject( IProjectAmender amender )
12    {
13        // The scope is the Console class, which belongs to a referenced assembly.
14        amender.SelectReflectionType( typeof(Console) ).InterceptMethods(
15            b => b
16                .Type( typeof(LegacyLogger) )
17                .Methods( "Write" )
18                .RedirectToExistingMethod( typeof(Logger).AsINamedType().Methods.OfName( "Write" ).Single() ) );
19    }
20}
21
1using System;
2
3namespace Doc.LAMA1001.Error;
4
5public static class LegacyLogger
6{
7    public static void Write( string message ) => Console.WriteLine( message );
8}
9
10public static class Logger
11{
12    public static void Write( string message ) => Console.WriteLine( $"[{DateTime.Now:T}] {message}" );
13}
14
15internal class OrderService
16{
17    public void Place() => LegacyLogger.Write( "Order placed." );
18}
19

Resolution

Select a scope that is declared in your project: a namespace, a type, a member or the whole compilation. To intercept the calls to a method of a referenced assembly, register the interceptor on the declaration that contains the calls, and name the intercepted method with the Type and Methods methods of the interception builder. In the following example, the fabric registers the interceptor on the whole project.

1using System;
2using System.Linq;
3using Metalama.Extensions.Interceptors;
4using Metalama.Framework.Code;
5using Metalama.Framework.Fabrics;
6
7namespace Doc.LAMA1001.Fixed;
8
9public class Fabric : ProjectFabric
10{
11    public override void AmendProject( IProjectAmender amender )
12    {
13        // The scope is the project, whose source code contains the calls to intercept.
14        amender.InterceptMethods(
15            b => b
16                .Type( typeof(LegacyLogger) )
17                .Methods( "Write" )
18                .RedirectToExistingMethod( typeof(Logger).AsINamedType().Methods.OfName( "Write" ).Single() ) );
19    }
20}
21
Source Code
1using System;
2
3namespace Doc.LAMA1001.Fixed;
4
5public static class LegacyLogger
6{
7    public static void Write( string message ) => Console.WriteLine( message );
8}
9
10public static class Logger
11{
12    public static void Write( string message ) => Console.WriteLine( $"[{DateTime.Now:T}] {message}" );
13}
14
15internal class OrderService
16{
17    public void Place() => LegacyLogger.Write( "Order placed." );
18}
19
Transformed Code
1using System;
2
3namespace Doc.LAMA1001.Fixed;
4
5public static class LegacyLogger
6{
7    public static void Write(string message) => Console.WriteLine(message);
8}
9
10public static class Logger
11{
12    public static void Write(string message) => Console.WriteLine($"[{DateTime.Now:T}] {message}");
13}
14
15internal class OrderService
16{
17    public void Place() => Logger.Write("Order placed.");
18}
19

See also