| Severity | Error |
| Reported by | PostSharp |
| Message | The parameter "<Parameter>" of the advice "<Advice>" is of type "<ParameterType>", which cannot receive the value of type "<ValueType>" bound by <Binding>. The parameter must be of type "<ValueType>", or of a base type when "<ValueType>" is a reference type. |
Cause
Several binding attributes give a value of a fixed type: DeclarationIdentifierAttribute gives a DeclarationIdentifier, AsyncCallIdAttribute an AsyncCallId, AwaitedTaskAttribute a Task. PostSharp passes the value without converting it, so the parameter must be able to hold it:
- When
<ValueType>is a value type, the parameter must be of this exact type, because PostSharp does not box the value. An object parameter is not accepted. - When
<ValueType>is a reference type, the parameter can be of this type or of a base type.
When the parameter type does not follow this rule, PostSharp reports LA0211 on the parameter. <Binding> is the binding attribute as you write it, such as [DeclarationIdentifier]. The table in Binding attributes gives the parameter type that each attribute accepts.
In the following example, the methodId parameter receives a DeclarationIdentifier, which is a struct, as an object.
using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0211_Error;
[PSerializable]
public class CountCallsAttribute : MethodLevelAspect
{
private static readonly Dictionary<object, int> _counts = new();
[OnMethodEntryAdvice]
// DeclarationIdentifier is a struct, and PostSharp does not box it into an object parameter.
public void OnEntry( [DeclarationIdentifier] object methodId, [DeclarationName] string methodName )
{
_counts.TryGetValue( methodId, out int count );
_counts[methodId] = count + 1;
Console.WriteLine( $"{methodName}: call number {count + 1}" );
}
}
public class OrderService
{
[CountCalls]
public void Ship( int orderId )
{
}
}
public static class Program
{
public static void Main()
{
OrderService service = new();
service.Ship( 1 );
service.Ship( 2 );
}
}
error LA0211: LA0211_Error.cs(17,57): The parameter "methodId" of the advice "Errors.LA0211_Error.CountCallsAttribute.OnEntry(System.Object, System.String)" is of type "object", which cannot receive the value of type "PostSharp.Reflection.DeclarationIdentifier" bound by [DeclarationIdentifier]. The parameter must be of type "PostSharp.Reflection.DeclarationIdentifier", or of a base type when "PostSharp.Reflection.DeclarationIdentifier" is a reference type.
Resolution
Change the type of the parameter to the type of the bound value, <ValueType>. When you need the value as an object, convert it in the body of the advice.
In the following example, the methodId parameter is of type DeclarationIdentifier, and the advice boxes it when it uses it as the key of a dictionary of objects.
using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0211_Fixed;
[PSerializable]
public class CountCallsAttribute : MethodLevelAspect
{
private static readonly Dictionary<object, int> _counts = new();
[OnMethodEntryAdvice]
// The parameter has the exact type of the bound value.
public void OnEntry( [DeclarationIdentifier] DeclarationIdentifier methodId, [DeclarationName] string methodName )
{
_counts.TryGetValue( methodId, out int count );
_counts[methodId] = count + 1;
Console.WriteLine( $"{methodName}: call number {count + 1}" );
}
}
public class OrderService
{
[CountCalls]
public void Ship( int orderId )
{
}
}
public static class Program
{
public static void Main()
{
OrderService service = new();
service.Ship( 1 );
service.Ship( 2 );
}
}
Ship: call number 1
Ship: call number 2
See Also
Reference
AdviceParameterAttribute
DeclarationIdentifierAttribute
DeclarationIdentifier
Other Resources