| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The member '<Member>' requires <RequiredArgumentsCount> argument(s), but the invocation passes <ActualArgumentsCount>. |
Cause
In a template, you can generate a call to a method, a constructor, or an event that you only know as a compile-time declaration, such as an IMethod, by calling the Invoke method of its invoker. The C# compiler can't check the arguments of this call, because it doesn't know the signature of the target member when it compiles the aspect. Metalama checks them when it executes the template.
Metalama reports LAMA0012 when the number of arguments passed to Invoke is different from the number of parameters of the invoked member, and the member has no params parameter. Optional parameters aren't taken into account: you must pass a value for each parameter. In the message, <Member> is the invoked member, <RequiredArgumentsCount> is the number of its parameters, and <ActualArgumentsCount> is the number of arguments passed to Invoke. The diagnostic is reported on the declaration to which the aspect is applied.
When the member has a params parameter and receives too few arguments, Metalama reports LAMA0013 instead.
In the following example, the Audit aspect calls the WriteAudit method of the target type, which has two parameters, with a single argument.
1using Metalama.Framework.Aspects;
2using System.Linq;
3
4namespace Doc.LAMA0012.Error;
5
6public class AuditAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Finds the WriteAudit method of the target type.
11 var writeAudit = meta.Target.Type.Methods.OfName( "WriteAudit" ).Single();
12
13 // Error: WriteAudit has two parameters, but only one argument is passed.
14 writeAudit.Invoke( meta.Target.Method.Name );
15
16 return meta.Proceed();
17 }
18}
19
1using System;
2
3namespace Doc.LAMA0012.Error;
4
5internal class OrderService
6{
7 [Audit]
Error LAMA0012: The member 'OrderService.WriteAudit(string, string)' requires 2 argument(s), but the invocation passes 1.
8 public void PlaceOrder( string product, int quantity )
9 {
10 Console.WriteLine( $"Placing an order for {quantity} {product}." );
11 }
12
13 private void WriteAudit( string typeName, string methodName )
14 {
15 Console.WriteLine( $"Audit: {typeName}.{methodName}" );
16 }
17}
18
Resolution
Pass exactly one argument for each parameter of the invoked member, in the order of the parameters. If your aspect must work with members of several signatures, examine the Parameters collection of the member before invoking it, and build the arguments accordingly, or report a diagnostic when the signature isn't supported.
In the following example, the aspect passes both arguments to WriteAudit.
1using Metalama.Framework.Aspects;
2using System.Linq;
3
4namespace Doc.LAMA0012.Fixed;
5
6public class AuditAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Finds the WriteAudit method of the target type.
11 var writeAudit = meta.Target.Type.Methods.OfName( "WriteAudit" ).Single();
12
13 // Fixed: one argument is passed for each parameter of WriteAudit.
14 writeAudit.Invoke( meta.Target.Type.Name, meta.Target.Method.Name );
15
16 return meta.Proceed();
17 }
18}
19
1using System;
2
3namespace Doc.LAMA0012.Fixed;
4
5internal class OrderService
6{
7 [Audit]
8 public void PlaceOrder( string product, int quantity )
9 {
10 Console.WriteLine( $"Placing an order for {quantity} {product}." );
11 }
12
13 private void WriteAudit( string typeName, string methodName )
14 {
15 Console.WriteLine( $"Audit: {typeName}.{methodName}" );
16 }
17}
18
1using System;
2
3namespace Doc.LAMA0012.Fixed;
4
5internal class OrderService
6{
7 [Audit]
8 public void PlaceOrder(string product, int quantity)
9 {
10 WriteAudit("OrderService", "PlaceOrder");
11 Console.WriteLine($"Placing an order for {quantity} {product}.");
12 }
13 private void WriteAudit(string typeName, string methodName)
14 {
15 Console.WriteLine($"Audit: {typeName}.{methodName}");
16 }
17}
18