C # designers have never been AOP supporters, there is no easy way to intercept method calls without using proxies and marshaling, which have their drawbacks! If someone wants to intercept method / property calls (e.g. cross cut issues), I found RealProxy to help.
RealProxy From MSDN:
A client that uses the object through any kind of remote boundary, in fact using a transparent proxy for the object. A transparent proxy provides the illusion that the actual object is in client space. This is achieved by redirecting calls made to it by a real object using the remote access infrastructure.
Note. A type proxied using RealProxy must either be an interface or inherit from MarshalByRefObject .
Here's some implementation of RealProxy using the Factory method to create a proxy object at runtime:
public abstract class RuntimeProxy { public static readonly object Default = new object(); public static Target Create<Target>(Target instance, RuntimeProxyInterceptor interceptor) where Target : class { return (Target)new InternalProxy<Target>(instance, interceptor).GetTransparentProxy(); } public static Target Create<Target>(Target instance, Func<RuntimeProxyInvoker, object> factory) where Target : class { return (Target)new InternalProxy<Target>(instance, new InternalRuntimeProxyInterceptor(factory)).GetTransparentProxy(); } class InternalProxy<Target> : RealProxy where Target : class { readonly object Instance; readonly RuntimeProxyInterceptor Interceptor; public InternalProxy(Target instance, RuntimeProxyInterceptor interceptor) : base(typeof(Target)) { Instance = instance; Interceptor = interceptor; } public override IMessage Invoke(IMessage msg) { var methodCall = (IMethodCallMessage)msg; var method = (MethodInfo)methodCall.MethodBase; try { var result = Interceptor.Invoke(new InternalRuntimeProxyInterceptorInvoker(Instance, method, methodCall.InArgs)); if (result == RuntimeProxy.Default) result = method.ReturnType.IsPrimitive ? Activator.CreateInstance(method.ReturnType) : null; return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall); } catch (Exception ex) { if (ex is TargetInvocationException && ex.InnerException != null) return new ReturnMessage(ex.InnerException, msg as IMethodCallMessage); return new ReturnMessage(ex, msg as IMethodCallMessage); } } } class InternalRuntimeProxyInterceptor : RuntimeProxyInterceptor { readonly Func<RuntimeProxyInvoker, object> Factory; public InternalRuntimeProxyInterceptor(Func<RuntimeProxyInvoker, object> factory) { this.Factory = factory; } public override object Invoke(RuntimeProxyInvoker invoker) { return Factory(invoker); } } class InternalRuntimeProxyInterceptorInvoker : RuntimeProxyInvoker { public InternalRuntimeProxyInterceptorInvoker(object target, MethodInfo method, object[] args) : base(target, method, args) { } } } public abstract class RuntimeProxyInterceptor { public virtual object Invoke(RuntimeProxyInvoker invoker) { return invoker.Invoke(); } } public abstract class RuntimeProxyInvoker { public readonly object Target; public readonly MethodInfo Method; public readonly ReadOnlyCollection<object> Arguments; public RuntimeProxyInvoker(object target, MethodInfo method, object[] args) { this.Target = target; this.Method = method; this.Arguments = new ReadOnlyCollection<object>(args); } public object Invoke() { return Invoke(this.Target); } public object Invoke(object target) { if (target == null) throw new ArgumentNullException("target"); try { return this.Method.Invoke(target, this.Arguments.ToArray()); } catch (TargetInvocationException ex) { throw ex.InnerException; } } }
You can use RuntimeProxy as Factory to create an object proxy object and intercept all method / property calls and call the actual method.
Here is an example:
class SomeClass : MarshalByRefObject { public int Mul(int a, int b) { return a * b; } public void SetValue(int val) { this.Val = val; } public int Val { get; set; } }
Use the RuntimeProxy class to create a proxy for an instance of the SomeClass class and intercept calls:
var test = new SomeClass(); var proxy = RuntimeProxy.Create(test, t => { // cross-cut here return t.Invoke(); // invoke the actual call }); var res = proxy.Mul(3, 4); // method with return value proxy.SetValue(2); // void method, setting some property var val = proxy.Val; // property access
You can use interface types in case you do not want to inherit the MarshalByRefObject class.