Search code examples
c#.netaoppostsharp

PostSharp: Applying Advice to External Type


I'm trying to apply some advice at call-site pointcuts in external/3rd party assemblies using PostSharp 4.3.24 but I'm running into some issues. In the simplest example, I'm trying to record some information about all SQL executed by the application. My approach was to apply OnMethodBoundaryAdvice to all SQLCommand.Execute* methods (we don't use the legacy async pattern supplied by the BeginExecute* methods, so I'm intentionally not including them). I've tried this using both the Multicast section of the PostSharp solution configuration file (MySolution.pssln file) as well as the following equivalent assembly-wide multicast attribute application:

[assembly:Blah.Telemetry.Aspects.SqlCommandTelemetryAspect(
    AttributeTargetAssemblies = "System.Data", 
    AttributeTargetTypes = "System.Data.SqlClient.SqlCommand", 
    AttributeTargetMembers = "Execute*"
)]

My Aspect declaration currently looks as such:

[MulticastAttributeUsage(AllowExternalAssemblies = true, Inheritance = MulticastInheritance.Multicast)]
[PSerializable]
public sealed class SqlCommandTelemetryAspect : OnMethodBoundaryAspect { /*...*/ }

I have tried various combinations of target types, inheritance values, etc. in the MulticastAttributeUsage, but get the same confusing results every time.

The issue I'm having is that the advice is only applied to a single SqlCommand method (ExecuteReader). I also need it applied to all the other Execute methods (ExecuteNonQuery, for example) and all overloads. I have also tried targeting DbCommand.Execute* which contains the abstract definition of some of these overloads. When I taget ExecuteNonQuery directly (instead of using wildcards or regex) I get the following warning implying that no advice was applied (and decompilation confirms this):

POSTSHARP : postsharp warning PS0131: The project 'Blah.Framework.dll' does not contain any aspect or other transformation[...]

Am I doing something wrong or maybe is this a bug in PostSharp?


Solution

  • The related bug has been fixed in PostSharp 4.3.26. It is now possible to apply OnMethodBoundary and MethodInterception aspects to abstract methods in external assemblies using aspect provider.

    For example:

    [assembly:MyAspectProvider(
        AttributeTargetAssemblies = "System.Data", 
        AttributeTargetTypes = "System.Data.Common.DbCommand", 
        AttributeTargetMembers = "Execute*"
    )]
    
    [PSerializable]
    public class MyAspectProvider : MethodLevelAspect, IAspectProvider
    {
        public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
        {
            yield return new AspectInstance(targetElement, new MyAspect());
        }
    }
    
    [PSerializable]
    public class MyAspect : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            // ...
        }
    }