Open sandboxFocusImprove this doc

LAMA0071: The type arguments of a generic method can't be inferred

Severity Error
Reported by Metalama.Framework
Message Cannot infer the type arguments for method '<Method>'. Supply the type arguments explicitly using IMethod.MakeGenericInstance.

Cause

When a template gets a generic method from the code model, for instance with meta.Target.Type.Methods.OfName( ... ), the IMethod represents the generic method definition: its type arguments are still its type parameters, such as T. When you call Invoke on this method, Metalama must decide which type arguments to generate in the invocation.

Metalama tries to infer each type argument from the types of the arguments that you pass to Invoke, by matching them with the types of the parameters. Metalama reports LAMA0071 when this inference fails, for instance because:

  • A type parameter doesn't appear in the types of the parameters that receive an argument.
  • The arguments give conflicting types for the same type parameter, for instance int and string.
  • A parameter has a generic type, such as List<T>, and the argument has a different generic type, such as HashSet<int>.

In the message, <Method> is the generic method. The error is located on the declaration to which the aspect is applied.

In the following example, the Audit aspect invokes the generic method WriteAudit<TCategory>( string operation ), but TCategory can't be inferred from a string argument.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System.Linq;
4
5namespace Doc.LAMA0071.Error;
6
7public class AuditAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        var writeAudit = meta.Target.Type.Methods.OfName( "WriteAudit" ).Single();
12
13        // Error: the type argument of WriteAudit<TCategory> can't be inferred from a string argument.
14        writeAudit.Invoke( meta.Target.Method.Name );
15
16        return meta.Proceed();
17    }
18}
19
1using System;
2
3namespace Doc.LAMA0071.Error;
4
5internal class OrderService
6{
7    [Audit]
    Error LAMA0071: Cannot infer the type arguments for method 'OrderService.WriteAudit<TCategory>(string)'. Supply the type arguments explicitly using IMethod.MakeGenericInstance.

8    public void PlaceOrder( int productId ) { }
9
10    public void WriteAudit<TCategory>( string operation )
11    {
12        Console.WriteLine( $"[{typeof(TCategory).Name}] {operation}" );
13    }
14}
15

Resolution

Supply the type arguments explicitly by calling MakeGenericInstance on the method before invoking it. Extension methods of GenericExtensions add overloads that accept a list of IType or Type arguments. The WithTypeArguments methods suggested by older versions of Metalama are obsolete. In the following example, the aspect passes the target type as the type argument.

If the arguments should allow the inference, check that their types match the types of the parameters.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System.Linq;
4
5namespace Doc.LAMA0071.Fixed;
6
7public class AuditAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        var writeAudit = meta.Target.Type.Methods.OfName( "WriteAudit" ).Single();
12
13        // Fixed: the type argument is supplied explicitly.
14        writeAudit.MakeGenericInstance( meta.Target.Type ).Invoke( meta.Target.Method.Name );
15
16        return meta.Proceed();
17    }
18}
19
Source Code
1using System;
2
3namespace Doc.LAMA0071.Fixed;
4
5internal class OrderService
6{
7    [Audit]
8    public void PlaceOrder( int productId ) { }
9
10    public void WriteAudit<TCategory>( string operation )
11    {
12        Console.WriteLine( $"[{typeof(TCategory).Name}] {operation}" );
13    }


14}
15
Transformed Code
1using System;
2
3namespace Doc.LAMA0071.Fixed;
4
5internal class OrderService
6{
7    [Audit]
8    public void PlaceOrder(int productId)
9    {
10        WriteAudit<OrderService>("PlaceOrder");
11    }
12    public void WriteAudit<TCategory>(string operation)
13    {
14        Console.WriteLine($"[{typeof(TCategory).Name}] {operation}");
15    }
16}
17

See also