Search code examples
postsharp

PostSharp: How to mix semantic and non-semantic advising?


For example I have OnMethodBoundaryAspect logger which I apply to iterator method:

public override void OnEntry(MethodExecutionArgs args) {
    BeginMethodScope( args );
    Logger.LogRequestEntry();
}

public override void OnSuccess(MethodExecutionArgs args) {
    Logger.LogRequestSuccess();
}

public override void OnException(MethodExecutionArgs args) {
    Logger.LogRequestError( args.Exception );
}

public override void OnExit(MethodExecutionArgs args) {
    EndMethodScope( args );
}

If I use semantic advising:

  • OnEntry is invoked when IEnumerable is started.
  • OnExit is invoked when IEnumerable is finished.

If I use non-semantic advising:

  • OnEntry/OnExit is invoked before/after creation of IEnumerable.

But what if I want to use both ways at once? Because I want to log the method call itself (not iteration starting).

Maybe I can achieve this with low-level advices?


Solution

  • Yes, you can achieve this by creating two groups of advices within the same aspect, as shown in the example below.

    [PSerializable]
    public class MyAspect : MethodLevelAspect
    {
        [OnMethodEntryAdvice(SemanticallyAdvisedMethodKinds = SemanticallyAdvisedMethodKinds.None)]
        [AdviceDependency(AspectDependencyAction.Order, AspectDependencyPosition.Before, nameof(OnEntrySemantic))]
        [SelfPointcut]
        public void OnEntry( MethodExecutionArgs args )
        {
            Console.WriteLine("OnEntry");
        }
    
        [OnMethodExitAdvice( Master = nameof( OnEntry ) )]
        public void OnExit( MethodExecutionArgs args )
        {
            Console.WriteLine( "OnExit" );
        }
    
        [OnMethodEntryAdvice]
        [SelfPointcut]
        public void OnEntrySemantic( MethodExecutionArgs args )
        {
            Console.WriteLine( "OnEntrySemantic" );
        }
    
        [OnMethodExitAdvice( Master = nameof( OnEntrySemantic ) )]
        public void OnExitSemantic( MethodExecutionArgs args )
        {
            Console.WriteLine( "OnExitSemantic" );
        }
    }
    

    P.S. The current version of PostSharp will emit a build-time warning for the example above. This is due to a bug that should be fixed in one of the upcoming releases. The run-time behavior of the aspect is not affected.