Search code examples
c#inheritancepostsharpaop

PostSharp LocationInterceptionAspect not being applied to inherited properties


I have created an attribute that inherits LocationInterceptionAspect. For demonstration purposes the code is as follows:

[Serializable]
public class RepeaterAttribute : LocationInterceptionAspect
{
    public override bool CompileTimeValidate(PostSharp.Reflection.LocationInfo locationInfo)
    {
        var propertyInfo = locationInfo.PropertyInfo;
        if (propertyInfo == null) return false;
        if (propertyInfo.PropertyType != typeof(String))
            return false;
        return base.CompileTimeValidate(locationInfo);
    }
    public override void OnSetValue(LocationInterceptionArgs args)
    {
        args.Value = ((String)args.Value) + ((String)args.Value);
        args.ProceedSetValue();
    }
}

I have a library called External and in it is a class called Parent.

namespace External
{
    public class Parent
    {
        public String ParentProperty { get; set; }
    }
}

In a console application I have a class called Child that inherits from Parent. The console application references the External library.

public class Child : External.Parent
{
    public String ChildProperty { get; set; }
}

In my console application my code is.

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var child = new Child();
            child.ParentProperty = "A";
            Console.WriteLine("This should be 'AA' : '{0}'", child.ParentProperty);
            child.ChildProperty = "B";
            Console.WriteLine("This should be 'BB' : '{0}'", child.ChildProperty);
            Console.ReadKey();
        }
    }
}

and in the console application's AssemblyInfo.cs I have:

[assembly: ConsoleApplication.Repeater(AttributeTargetTypes = "ConsoleApplication.Child")]

But when I run the Repeater attribute is not being applied to the inherited "ParentProperty" from the Parent class.


Solution

  • PostSharp is not able to change classes in different assemblies that in the one it is transforming. The base property is declared in a different assembly. This is a limitation of LocationInterceptionAspect.

    You can use MethodInterception, which supports intercepting methods in different assemblies:

    [Serializable]
    public class SetterRepeaterAttribute : MethodInterceptionAspect
    {
        public override void OnInvoke( MethodInterceptionArgs args )
        {
            args.Arguments[0] = ((String)args.Arguments[0]) + ((String)args.Arguments[0]);
            args.Proceed();
        }
    }
    

    And multicast it on assembly level to the setter of the base class:

    [assembly: ConsoleApplication2.SetterRepeater(
        AttributeTargetMembers = "set_ParentProperty", 
        AttributeTargetTypes = "External.Parent", 
        AttributeTargetAssemblies = "regex:.*")]
    

    Note that in this case the interception is done at the call site level, the ParentProperty setter is not changed itself. Calls from the original assembly won't be intercepted.