Created
March 29, 2012 23:08
-
-
Save gabrielgreen/2244765 to your computer and use it in GitHub Desktop.
AOP.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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