| Severity | Error |
| Reported by | PostSharp |
| Message | Advice "<Advice>" is not grouped with a non-async OnMethodInvokeAdvice, therefore its UnsupportedTargetAction property cannot be set to Fallback. |
Cause
An advice marked with OnMethodInvokeAsyncAdvice intercepts only the methods that return a Task or a Task<TResult>. When the UnsupportedTargetAction property of the group is Fallback, an advice marked with OnMethodInvokeAdvice, in the same group, intercepts the other methods without async semantics. The property applies to the whole group, and can be set on any one advice of the group.
PostSharp reports LA0173 on the async advice <Advice> when the property is Fallback and the group has no such advice: there is nothing to fall back to. PostSharp checks the group itself, whatever methods the aspect is applied to.
In the following example, the [Log] aspect has only an async interception advice, which asks for a fallback.
using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0173_Error;
[PSerializable]
public class LogAttribute : MethodLevelAspect
{
// Fallback needs a non-async OnMethodInvokeAdvice in the group, and there is none.
[OnMethodInvokeAsyncAdvice( UnsupportedTargetAction = UnsupportedTargetAction.Fallback )]
public async Task OnInvokeAsync( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name} asynchronously." );
await args.ProceedAsync();
}
}
public class PriceService
{
[Log]
public async Task<decimal> GetPriceAsync( string product )
{
await Task.Yield();
return product.Length * 1.5m;
}
[Log]
public async ValueTask<int> GetStockAsync( string product )
{
await Task.Yield();
return product.Length * 10;
}
}
public static class Program
{
public static async Task Main()
{
PriceService service = new();
Console.WriteLine( await service.GetPriceAsync( "Coffee" ) );
Console.WriteLine( await service.GetStockAsync( "Coffee" ) );
}
}
error LA0173: LA0173_Error.cs(14,23): Advice "Errors.LA0173_Error.LogAttribute.OnInvokeAsync(PostSharp.Aspects.MethodInterceptionArgs)" is not grouped with a non-async OnMethodInvokeAdvice, therefore its UnsupportedTargetAction property cannot be set to Fallback.
Resolution
- Add an advice marked with OnMethodInvokeAdvice to the group. An advice without pointcut and without Group joins the group of its class that has no advice of its kind yet. When several groups of the class have none, give the two advices the same Group value.
- Otherwise, set UnsupportedTargetAction to Ignore to leave the unsupported methods alone, or remove the property to get LA0172 on each of them.
In the following example, the OnInvoke advice joins the group of OnInvokeAsync, and intercepts the method that returns a ValueTask<int>.
using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0173_Fixed;
[PSerializable]
public class LogAttribute : MethodLevelAspect
{
[OnMethodInvokeAsyncAdvice( UnsupportedTargetAction = UnsupportedTargetAction.Fallback )]
public async Task OnInvokeAsync( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name} asynchronously." );
await args.ProceedAsync();
}
// This advice joins the group of OnInvokeAsync and intercepts the methods that async interception does not support.
[OnMethodInvokeAdvice]
public void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
}
public class PriceService
{
[Log]
public async Task<decimal> GetPriceAsync( string product )
{
await Task.Yield();
return product.Length * 1.5m;
}
[Log]
public async ValueTask<int> GetStockAsync( string product )
{
await Task.Yield();
return product.Length * 10;
}
}
public static class Program
{
public static async Task Main()
{
PriceService service = new();
Console.WriteLine( await service.GetPriceAsync( "Coffee" ) );
Console.WriteLine( await service.GetStockAsync( "Coffee" ) );
}
}
Calling GetPriceAsync asynchronously.
9.0
Calling GetStockAsync.
60
See Also
Reference
OnMethodInvokeAsyncAdvice
OnMethodInvokeAdvice
GroupingAdvice
Other Resources
Advice Methods
Semantic Advising of Iterator and Async Methods