A basic proxy for intercepting method calls (Part –1)

In this post, i am going to show how you can write your own proxy for delegating calls. This just shows a way how you can handle it on your own but for complex interceptions its always wise to use alpha/beta/tested solutions. The post is more of an under the hood or aims to solve simple interception tasks where you might not need a full featured dynamic proxy or can be useful in building something that requires similar techniques which can move you further.

Let’s start by considering a simple class

publicclassTestClass

{

publicvirtualvoid TestCall()

{

thrownewException("Failed.");

}

}

Here, during the creation of proxy i will hook the method with an interceptor that will alternate the execution process from original code. At a glace, our interceptor looks like:

publicinterfaceIInterceptor

{

void Intercept();

}

As it shows, we are going to do a fairly basic implementation.To start, let’s create an implementation on it named BasicInterceptor where inside the Intercept call it just prints a line.

publicclassBasicInterceptor : IInterceptor

{

publicvoid Intercept()

{

System.Console.WriteLine("Intercepted");

}

}

Once, we are done with our proxy the result code will look something like below:

var proxy = newProxy(typeof(TestClass));

var test = (TestClass) proxy.Create(newBasicInterceptor());

test.TestCall();

And the above test.TestCall() call Instead of throwing an exception, it will print our expected line. We can here see that I first created the proxy with the given type/class then during the instantiation i hooked that up with our interceptor. Hence, on my first step I created a class deriving from the specified type and expanded its constructor(s) to take an IInterceptor implementation as parameter.

Accordingly, I first created a TypeBuilder instance from System.Refleciton.Emitwhich is pretty much common in all kind and that looks like:

Tip 1 : OpCodes.Ldarg_0 is like “this” context, which is not needed for static calls. If your are calling a field of the class or referring method arguments, always start with LdArgs_0 or you might end up with “JIT encountered an internal limitation” error.

Tip 2: In MSIL every method must terminate with OpCodes.Ret regardless its void or not. The difference between void and non-void calls is that the top of evaluation stack is not empty.

Now, as we set it up , we need to hook the interceptor in each method that is marked as virtual. First, let’s create the target method attribute :

Again, before loading the interceptor field on to the evaluation stack , I used Ldarg_0 or “this” equivalent . If you notice, you will see that I have used OpCodes.Callvirt instead of OpCodes.Call. This will actually call the base method rather the implemented. This difference is important if you need to distinguish between base and implemented calls. Unless otherwise, it is better to go with OpCodes.Callvirt that will do the work for you if “base” is something not in your consideration.

Finally, you need to create the type and instance that will be initiated by Proxy.Create() call.

Type proxy = this.typeBuilder.CreateType();

returnActivator.CreateInstance(proxy, args);

That’s it, we ended up with a simple proxy. In the next post, i will enhance it with parameters consideration and show how to handle return value from proxy.