I'm a little concerned that this much inheritance could be a design flaw or at least a huge maintenance headache, but assuming that it's not, let's soldier on...
I don't think there's a way to do exactly what you want to do. Even if PostSharp had the ability, C# needs to know the type at compile time (before PostSharp even touches it).
I suggest that you use CompileTimeValidate to verify that the class the aspect is used on is of a certain type, and once that's in place, you can cast args.Instance
to your interface type without worrying about an invalid cast exception. And if that class doesn't implement IEnabled
, then you'll get a compile-time error.
Here's a quick example:
public interface IEnabled
{
bool Enabled { get; }
}
[Serializable]
public class ModularAttribute : OnMethodBoundaryAspect
{
public override bool CompileTimeValidate(System.Reflection.MethodBase method)
{
if(typeof(IEnabled).IsAssignableFrom(method.DeclaringType))
return true;
Message.Write(method, SeverityType.Error, "MYERR001", "Aspect can't be used on a class that doesn't implement IEnabled");
return false;
}
public override void OnEntry(MethodExecutionArgs args)
{
var obj = (IEnabled) args.Instance; // this will always be a safe cast
if(!obj.Enabled)
args.FlowBehavior = FlowBehavior.Return;
}
}
There's a catch though: you don't want this aspect being used on the Enabled property itself, because that would cause a stack overflow (i.e. the aspect checks the property, causing the aspect to check the property, etc). So make sure to exclude Enabled
using AttributeExclude
.
class Program
{
static void Main(string[] args)
{
var b = new B();
b.Enabled = false;
b.SomeMethod();
b.AnotherMethod();
}
}
public interface IEnabled
{
bool Enabled { get; }
}
[Modular(AttributeInheritance = MulticastInheritance.Multicast)]
public class A : IEnabled
{
[Modular(AttributeExclude = true)]
public bool Enabled { get; set; }
public void SomeMethod()
{
Console.WriteLine("in SomeMethod");
}
}
public class B : A
{
public void AnotherMethod()
{
Console.WriteLine("in AnotherMethod");
}
}