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.
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.