| Severity | Warning |
| Reported by | PostSharp |
| Message | Cannot apply the aspect "<Aspect>" to "<Target>" because "<Target>" is an aspect or a member of an aspect. The aspect is ignored. |
Cause
PostSharp does not apply aspects to aspects. When the target of an aspect is a type that implements IAspect, or a member of such a type, PostSharp skips the aspect. It reports LA0200 when you applied the aspect directly to this declaration with a custom attribute. When the aspect reaches an aspect class by multicasting, for example from an assembly-level attribute, PostSharp skips it silently.
<Target> is the aspect class, or its member that the aspect targets.
In the following example, the [Log] aspect is applied to a method of the [Retry] aspect. The build succeeds, but the output shows that ReportFailure is not logged.
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0200_Error;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( $"Entering {args.Method.Name}." );
}
[PSerializable]
public class RetryAttribute : MethodInterceptionAspect
{
public override void OnInvoke( MethodInterceptionArgs args )
{
for ( var attempt = 1; ; attempt++ )
{
try
{
args.Proceed();
return;
}
catch ( InvalidOperationException ) when ( attempt < 3 )
{
this.ReportFailure( attempt );
}
}
}
// PostSharp does not apply aspects to the members of an aspect.
[Log]
private void ReportFailure( int attempt ) => Console.WriteLine( $"Attempt {attempt} failed." );
}
public class PaymentService
{
private int _calls;
[Retry]
public void Charge()
{
this._calls++;
if ( this._calls < 3 )
{
throw new InvalidOperationException( "The payment gateway is unavailable." );
}
Console.WriteLine( "Payment accepted." );
}
}
public static class Program
{
public static void Main()
{
new PaymentService().Charge();
}
}
warning LA0200: LA0200_Error.cs(35,18): Cannot apply the aspect "Errors.LA0200_Error.LogAttribute" to "Errors.LA0200_Error.RetryAttribute.ReportFailure(System.Int32)" because "Errors.LA0200_Error.RetryAttribute.ReportFailure(System.Int32)" is an aspect or a member of an aspect. The aspect is ignored.
Attempt 1 failed.
Attempt 2 failed.
Payment accepted.
Resolution
Move the code that needs the aspect to a class that is not an aspect, and apply the aspect there. Otherwise, remove the attribute, which has no effect.
In the following example, ReportFailure moves to the RetryLog class, so the [Log] aspect applies to it.
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0200_Fixed;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( $"Entering {args.Method.Name}." );
}
[PSerializable]
public class RetryAttribute : MethodInterceptionAspect
{
public override void OnInvoke( MethodInterceptionArgs args )
{
for ( var attempt = 1; ; attempt++ )
{
try
{
args.Proceed();
return;
}
catch ( InvalidOperationException ) when ( attempt < 3 )
{
RetryLog.ReportFailure( attempt );
}
}
}
}
public static class RetryLog
{
// The method is in a class that is not an aspect, so the aspect applies to it.
[Log]
public static void ReportFailure( int attempt ) => Console.WriteLine( $"Attempt {attempt} failed." );
}
public class PaymentService
{
private int _calls;
[Retry]
public void Charge()
{
this._calls++;
if ( this._calls < 3 )
{
throw new InvalidOperationException( "The payment gateway is unavailable." );
}
Console.WriteLine( "Payment accepted." );
}
}
public static class Program
{
public static void Main()
{
new PaymentService().Charge();
}
}
Entering ReportFailure.
Attempt 1 failed.
Entering ReportFailure.
Attempt 2 failed.
Payment accepted.
See Also
Reference
Other Resources