Apply an aspect to only methods that have a specific attribute
Asked Answered
T

1

6

I'm trying to set up a PostSharp aspect RunOutOfProcessAttribute so that it applies to:

  1. all public methods
  2. any method marked with the DoSpecialFunctionAttribute, regardless of member accessibility (public/protected/private/whatever).

So far, my RunOutOfProcessAttribute is defined thusly:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, TargetMemberAttributes = MulticastAttributes.Public)]
[AttributeUsage(AttributeTargets.Class)]
public class RunOutOfProcessAttribute : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs args)
    {
        ...
    }
}

The MulticastAttributeUsageAttribute already in place should fulfil criterion 1 above, but I've got no idea how to fulfil criterion 2, without simply duplicating the behaviour of the existing aspect into a new attribute.

How would I get this aspect to apply to any method marked with the DoSpecialFunctionAttribute, regardless of member accessibility (public/protected/private/whatever)?

Thoughtless answered 26/11, 2012 at 4:59 Comment(2)
im confused as to why this is required. If you already are going to have a DoSpecialFunctionAttribute why not just include the function to do this in that attribute? rather than creating yet ANOTHER aspect.Counterweigh
I want to be able to put RunOutOfProcessAttribute on a class, as it more defines a class behaviour than a method behaviour. RunOutOfProcessAttribute should operate on all public class methods in addition to any protected one marked with DoSpecialFunctionAttribute. DoSpecialFunctionAttribute will not be an aspect.Thoughtless
T
6

Here's the solution:

  • Target all methods with [MulticastAttributeUsage(MulticastTargets.Method)]
  • Override CompileTimeValidate(MethodBase method). Set up the return values such that CompileTimeValidate returns true on appropriate targets, false on targets to silently ignore, and throws an exception when the user should be alerted that Aspect usage is inappropriate (this is detailed in the PostSharp documentation).

In code:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method)]
[AttributeUsage(AttributeTargets.Class)]
public class RunOutOfProcessAttribute : MethodInterceptionAspect
{
    protected static bool IsOutOfProcess;

    public override void OnInvoke(MethodInterceptionArgs args)
    {
        ...
    }

    public override bool CompileTimeValidate(MethodBase method)
    {
        if (method.DeclaringType.GetInterface("IDisposable") == null)
            throw new InvalidAnnotationException("Class must implement IDisposable " + method.DeclaringType);

        if (!method.Attributes.HasFlag(MethodAttributes.Public) && //if method is not public
            !MethodMarkedWith(method,typeof(InitializerAttribute))) //method is not initialiser
            return false; //silently ignore.

        return true;
    }
}
Thoughtless answered 27/11, 2012 at 2:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.