There are a a lot of questions and answers around AOP in .NET here on Stack Overflow, often mentioning PostSharp and other third-party products. So there seems to be qu
I'm not sure where you got that methods have to be virtual from. We use Postsharp to time and log calls to WCF service interface implementations utilizing the OnMethodBoundaryAspect to create an attribute we can decorate the classes with. Quick Example:
[Serializable]
public class LogMethodCallAttribute : OnMethodBoundaryAspect
{
public Type FilterAttributeType { get; set; }
public LogMethodCallAttribute(Type filterAttributeType)
{
FilterAttributeType = filterAttributeType;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
if (!Proceed(eventArgs)) return;
Console.WriteLine(GetMethodName(eventArgs));
}
public override void OnException(MethodExecutionEventArgs eventArgs)
{
if (!Proceed(eventArgs)) return;
Console.WriteLine(string.Format("Exception at {0}:\n{1}",
GetMethodName(eventArgs), eventArgs.Exception));
}
public override void OnExit(MethodExecutionEventArgs eventArgs)
{
if (!Proceed(eventArgs)) return;
Console.WriteLine(string.Format("{0} returned {1}",
GetMethodName(eventArgs), eventArgs.ReturnValue));
}
private string GetMethodName(MethodExecutionEventArgs eventArgs)
{
return string.Format("{0}.{1}", eventArgs.Method.DeclaringType, eventArgs.Method.Name);
}
private bool Proceed(MethodExecutionEventArgs eventArgs)
{
return Attribute.GetCustomAttributes(eventArgs.Method, FilterAttributeType).Length == 0;
}
}
And then us it like this:
[LogMethodCallAttribute(typeof(MyCustomAttribute))]
class MyClass
{
public class LogMe()
{
}
[MyCustomAttribute]
public class DoNotLogMe()
{
}
}
Works like a charm without having to make any methods virtual in Postsharp 1.5.6. Maybe they have changed it for 2.x but I certainly don't hope so - it would make it way less useful.
Update: I'm not sure if you can easily convince Postsharp to only inject code into certain methods based on with which attributes they are decorated. If you look at this tutorial it only shows ways of filtering on type and method names. We have solved this by passing the type we want to check on into the attribute and then in OnEntry you can use reflection to look for the attributes and decide whether to log or not. The result of that is cached so you only have to do it on the first call.
I adjusted the code above to demonstrate the idea.