Skip to content

Instantly share code, notes, and snippets.

@gabrielgreen
Created March 29, 2012 23:08
Show Gist options
  • Save gabrielgreen/2244765 to your computer and use it in GitHub Desktop.
Save gabrielgreen/2244765 to your computer and use it in GitHub Desktop.
AOP.cs
using System;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using DirectTrack;
using System.Linq;
namespace AOP
{
/// <summary>
/// Hook on to before/after method call of target class.
/// </summary>
public class MethodBoundaryAspect : IMessageSink
{
private IMessageSink next;
public MethodBoundaryAspect(IMessageSink next)
{
this.next = next;
}
public IMessageSink NextSink
{
get { return next; }
}
IMessage IMessageSink.SyncProcessMessage(IMessage msg)
{
IMessage returnMethod = null;
object overrideReturnValue = null;
if(OnEvent(msg, returnMethod, out overrideReturnValue))
{
IMethodCallMessage methodMessage = (IMethodCallMessage)msg;
returnMethod = new ReturnMessage(overrideReturnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
return returnMethod;
}
returnMethod = next.SyncProcessMessage(msg);
OnEvent(msg, returnMethod, out overrideReturnValue);
return returnMethod;
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
throw new InvalidOperationException();
}
private bool OnEvent(IMessage msg, IMessage returnMessage, out object overrideReturnValue)
{
overrideReturnValue = null;
if (!(msg is IMethodMessage))
{
return false;
}
IMethodMessage methodMessage = msg as IMethodMessage;
Type methodMessageType = Type.GetType(methodMessage.TypeName);
object[] methodMessageArgs = methodMessage.Args;
if (returnMessage == null)
{
if (Before != null)
{
object handlerResult = Before(methodMessageType.Name, methodMessage.MethodName, null, methodMessageArgs);
if (handlerResult != null)
{
overrideReturnValue = handlerResult;
return true;
}
}
}
else
{
if (After != null)
{
object returnValue = null;
IMethodReturnMessage methodReturnMessage = returnMessage as IMethodReturnMessage;
if (methodReturnMessage != null)
{
returnValue = methodReturnMessage.ReturnValue;
}
After(methodMessageType.Name, methodMessage.MethodName, returnValue, methodMessageArgs);
}
}
return false;
}
public delegate object MethodBoundaryEvent(string targetType, string methodName, object returnValue, object[] args);
static public event MethodBoundaryEvent Before;
static public event MethodBoundaryEvent After;
}
[AttributeUsage(AttributeTargets.Class)]
public class MethodBoundaryAspectAttribute : ContextAttribute
{
public MethodBoundaryAspectAttribute()
: base("Aspect")
{
}
public override void GetPropertiesForNewContext(IConstructionCallMessage message)
{
message.ContextProperties.Add(new MethodBoundaryAspectProperty());
}
}
public class MethodBoundaryAspectProperty : IContextProperty, IContributeObjectSink
{
public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
{
return new MethodBoundaryAspect(next);
}
public void Freeze(Context newContext)
{
}
public bool IsNewContextOK(Context newCtx)
{
return true;
}
public string Name
{
get { return "AspectProperty"; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment