Open sandboxFocusImprove this doc

LAMA1024: The interceptor method can't be generated in the requested placement

Severity Error
Reported by Metalama.Extensions.Interceptors
Message The <Source> cannot generate the interceptor of the <Site> in the requested placement because <Reason>. The call site is left unchanged.

Cause

An interceptor redirects the calls to a method to another method that Metalama generates from a template. The aspect chooses where the generated method goes with PlaceInCallingType, PlaceInType or PlaceInStaticClass, and can adjust the method in the Configure delegate. The call site must be able to call the method at that place.

Metalama reports LAMA1024 when the generated method can't be placed as requested for a call site, and it leaves the call site unchanged. The <Source> placeholder describes the template and the aspect, <Site> the intercepted call, and <Reason> the cause. The most common ones are:

  • The accessibility that the Configure delegate assigns is more restrictive than the call site needs. For instance, a private method of another type can't be called.
  • The method is an instance method, but the call site has no this (it's in a static method or in a conditional access), or the method isn't placed in the calling type or one of its base types.
  • The name given to PlaceInStaticClass isn't a valid full class name, or the type given to PlaceInType doesn't exist.
  • The call site is in top-level statements, whose type can't be named, or the signature contains an anonymous type.

In the following example, the method is generated in Helpers and the Configure delegate makes it private, but the call is in Report.

1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4using System;
5
6namespace Doc.LAMA1024.Error;
7
8public class InterceptPrintAttribute : TypeAspect
9{
10    public override void BuildAspect( IAspectBuilder<INamedType> builder )
11        => builder.InterceptMethods(
12            i => i
13                .Type( typeof(Printer) ).Methods( "Print" )
14                .RedirectToSynthesizedMethod( nameof(this.Intercept) )
15                .PlaceInType( typeof(Helpers) )
16                .Configure( b =>
17                    {
18                        // Error: a private method of Helpers cannot be called from Report.
19                        b.Method.Accessibility = Accessibility.Private;
20                    } ) );
21
22    [Template]
23    public dynamic? Intercept()
24    {
25        Console.Write( "> " );
26
27        return meta.Proceed();
28    }
29}
30
1using System;
2
3namespace Doc.LAMA1024.Error;
4
5public static class Printer
6{
7    public static void Print( string value ) => Console.WriteLine( value );
8}
9
10public static class Helpers { }
11
12[InterceptPrint]
13public static class Report
14{
    Error LAMA1024: The interceptor template 'Intercept' registered by the aspect [InterceptPrintAttribute] applied to 'Report' cannot generate the interceptor of the call to 'Printer.Print(string)' in the requested placement because the accessibility Private of the interceptor method is more restrictive than the accessibility Internal that the call site needs. The call site is left unchanged.

15    public static void Run() => Printer.Print( "Hello" );
16}
17

Resolution

Read the reason in the message, and change the placement or the configuration of the aspect:

  • Remove the accessibility assignment, or assign an accessibility that the call site can use.
  • Place the method in the calling type with PlaceInCallingType, where a private method is enough.
  • Make the method static if the call site has no this.
  • Fix the type or class name given to PlaceInType or PlaceInStaticClass.

In the following example, the method is internal, so Report can call it.

1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4using System;
5
6namespace Doc.LAMA1024.Fixed;
7
8public class InterceptPrintAttribute : TypeAspect
9{
10    public override void BuildAspect( IAspectBuilder<INamedType> builder )
11        => builder.InterceptMethods(
12            i => i
13                .Type( typeof(Printer) ).Methods( "Print" )
14                .RedirectToSynthesizedMethod( nameof(this.Intercept) )
15                .PlaceInType( typeof(Helpers) )
16                .Configure( b =>
17                    {
18                        // Fixed: an internal method of Helpers can be called from Report.
19                        b.Method.Accessibility = Accessibility.Internal;
20                    } ) );
21
22    [Template]
23    public dynamic? Intercept()
24    {
25        Console.Write( "> " );
26
27        return meta.Proceed();
28    }
29}
30
Source Code
1using System;
2
3namespace Doc.LAMA1024.Fixed;
4
5public static class Printer
6{
7    public static void Print( string value ) => Console.WriteLine( value );
8}
9
10public static class Helpers { }
11
12[InterceptPrint]







13public static class Report
14{
15    public static void Run() => Printer.Print( "Hello" );
16}
17
Transformed Code
1using System;
2
3namespace Doc.LAMA1024.Fixed;
4
5public static class Printer
6{
7    public static void Print(string value) => Console.WriteLine(value);
8}
9
10public static class Helpers
11{
12    internal static void Printer_Print_Interceptor(string value)
13    {
14        Console.Write("> ");
15        Printer.Print(value);
16    }
17}
18
19[InterceptPrint]
20public static class Report
21{
22    public static void Run() => Helpers.Printer_Print_Interceptor(value: "Hello");
23}
24

See also