| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply the custom attribute "<Attribute>" on parameter "<Parameter>" of method "<Method>": the attribute cannot be applied to the parameters of a <Reason>. |
Cause
The TargetMemberAttributes property of the usage of an attribute class, or the AttributeTargetMemberAttributes property of an instance, filters the members that the attribute applies to by visibility, scope, virtuality and other attributes. For an attribute that targets parameters, the filter applies to the method that declares the parameter.
When the attribute is multicast, PostSharp skips the parameters of the methods that the filter excludes. When you apply the attribute directly to such a parameter, PostSharp reports PS0105 instead, because it cannot honor both the filter and your request. <Reason> names the attribute of the method that the filter excludes, for example private member or static member.
In the following example, the [Positive] aspect validates the parameters of public methods only, and it is applied to a parameter of the private method ApplyDiscount.
using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.PS0105_Error;
// Checks that a value is greater than zero. The aspect validates the parameters of public methods only.
[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Parameter, TargetMemberAttributes = MulticastAttributes.Public )]
public sealed class PositiveAttribute : LocationLevelAspect, ILocationValidationAspect<decimal>
{
public Exception? ValidateValue( decimal value, string locationName, LocationKind locationKind, LocationValidationContext context )
=> value > 0 ? null : new ArgumentOutOfRangeException( locationName, $"The {locationName} must be positive." );
}
public class OrderService
{
public void PlaceOrder( decimal amount, decimal discountRate )
{
Console.WriteLine( $"Order placed for {this.ApplyDiscount( amount, discountRate ):0.00}." );
}
// The aspect is applied to a parameter of a private method.
private decimal ApplyDiscount( decimal amount, [Positive] decimal discountRate ) => amount * (1 - discountRate);
}
public static class Program
{
public static void Main()
{
OrderService service = new();
service.PlaceOrder( 100m, 0.1m );
try
{
service.PlaceOrder( 100m, -0.5m );
}
catch ( ArgumentOutOfRangeException e )
{
Console.WriteLine( $"Rejected: {e.ParamName}." );
}
}
}
error PS0105: PS0105_Error.cs(26,71): Cannot apply the custom attribute "Errors.PS0105_Error.PositiveAttribute" on parameter "discountRate : System.Decimal" of method "Errors.PS0105_Error.OrderService.ApplyDiscount(System.Decimal, System.Decimal)": the attribute cannot be applied to the parameters of a private member.
Resolution
- Apply the attribute to a parameter of a method that the filter accepts, for example to the parameter of the public method that passes the value to the excluded method.
- When the attribute must apply to such methods too, widen the
TargetMemberAttributesfilter of the attribute class, or set AttributeTargetMemberAttributes on the instance. - Otherwise, remove the attribute from the parameter.
In the following example, the aspect validates the discountRate parameter of the public PlaceOrder method.
using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.PS0105_Fixed;
// Checks that a value is greater than zero. The aspect validates the parameters of public methods only.
[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Parameter, TargetMemberAttributes = MulticastAttributes.Public )]
public sealed class PositiveAttribute : LocationLevelAspect, ILocationValidationAspect<decimal>
{
public Exception? ValidateValue( decimal value, string locationName, LocationKind locationKind, LocationValidationContext context )
=> value > 0 ? null : new ArgumentOutOfRangeException( locationName, $"The {locationName} must be positive." );
}
public class OrderService
{
// The aspect is applied to a parameter of the public method, which passes the value to the private method.
public void PlaceOrder( decimal amount, [Positive] decimal discountRate )
{
Console.WriteLine( $"Order placed for {this.ApplyDiscount( amount, discountRate ):0.00}." );
}
private decimal ApplyDiscount( decimal amount, decimal discountRate ) => amount * (1 - discountRate);
}
public static class Program
{
public static void Main()
{
OrderService service = new();
service.PlaceOrder( 100m, 0.1m );
try
{
service.PlaceOrder( 100m, -0.5m );
}
catch ( ArgumentOutOfRangeException e )
{
Console.WriteLine( $"Rejected: {e.ParamName}." );
}
}
}
Order placed for 90.00.
Rejected: discountRate.
See Also
Reference
MulticastAttributeUsageAttribute
MulticastAttributes
Other Resources
Adding Aspects to Multiple Declarations Using Attributes
Understanding Attribute Multicasting