Open sandboxFocusImprove this doc

LAMA1017: The accessibility of the generated interceptor method is inconsistent

Severity Error
Reported by Metalama.Extensions.Interceptors
Message The generated interceptor method '<Method>' must be <Accessibility>, but its signature contains the type '<Type>', which is less accessible. Choose a placement in a type that can access this type. The call sites are left unchanged.

Cause

An interceptor redirects the calls to a method to another method that Metalama generates from a template. The generated method has the parameters and the return type of the intercepted method. By default, Metalama places it in a generated internal static class, so it must be at least internal to be called from the call sites.

The C# rules of accessibility consistency forbid a method from exposing a type that is less accessible than the method itself. Metalama reports LAMA1017 when a parameter type or the return type of the generated method, such as a private nested type, is less accessible than the accessibility that the call sites need. Metalama then leaves the call sites unchanged.

In the following example, Process has a parameter of the private nested type Order, so a method of the generated internal class can't replace it.

1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4
5namespace Doc.LAMA1017.Error;
6
7public class InterceptProcessAttribute : TypeAspect
8{
9    public override void BuildAspect( IAspectBuilder<INamedType> builder )
10        => builder.InterceptMethods(
11            i => i
12                .Type( typeof(OrderService) ).Methods( "Process" )
13                // Error: by default, the method is generated in an internal class, which cannot expose the private type Order.
14                .RedirectToSynthesizedMethod( nameof(this.Intercept) ) );
15
16    [Template]
17    public dynamic? Intercept() => meta.Proceed();
18}
19
1namespace Doc.LAMA1017.Error;
2
3[InterceptProcess]
4public class OrderService
5{
6    private sealed class Order { }
7
8    private static void Process( Order order ) { }
9
    Error LAMA1017: The generated interceptor method 'OrderService_Process_Interceptor' must be internal, but its signature contains the type 'OrderService.Order', which is less accessible. Choose a placement in a type that can access this type. The call sites are left unchanged.

10    public static void Run() => Process( new Order() );
11}
12

Resolution

Choose a placement in a type that can access the less accessible type. When the calls to the intercepted method are in the type that declares the private type, use PlaceInCallingType: the generated method is then private, and it can expose the type. You can also use PlaceInType with a type that can access it.

Alternatively, make the type in the signature more accessible.

In the following example, the generated method is placed in OrderService.

1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4
5namespace Doc.LAMA1017.Fixed;
6
7public class InterceptProcessAttribute : TypeAspect
8{
9    public override void BuildAspect( IAspectBuilder<INamedType> builder )
10        => builder.InterceptMethods(
11            i => i
12                .Type( typeof(OrderService) ).Methods( "Process" )
13                // Fixed: the method is generated in OrderService, which can access the private type Order.
14                .RedirectToSynthesizedMethod( nameof(this.Intercept) )
15                .PlaceInCallingType() );
16
17    [Template]
18    public dynamic? Intercept() => meta.Proceed();
19}
20
Source Code
1namespace Doc.LAMA1017.Fixed;
2
3[InterceptProcess]
4public class OrderService
5{
6    private sealed class Order { }
7
8    private static void Process( Order order ) { }
9
10    public static void Run() => Process( new Order() );


11}
12
Transformed Code
1namespace Doc.LAMA1017.Fixed;
2
3[InterceptProcess]
4public class OrderService
5{
6    private sealed class Order { }
7
8    private static void Process(Order order) { }
9
10    public static void Run() => OrderService_Process_Interceptor(order: new Order());
11
12    private static void OrderService_Process_Interceptor(Order order)
13    {
14        Process(order);
15    }
16}
17

See also