This post originated from an RSS feed registered with Agile Buzz
by Joe Walnes.
Original Post: How to do Dynamic Proxies in C#
Feed Title: Joe's New Jelly
Feed URL: http://joe.truemesh.com/blog/index.rdf
Feed Description: The musings of a ThoughtWorker obsessed with Agile, XP, maintainability, Java, .NET, Ruby and OpenSource. Mmm'kay?
Background: A dynamic proxy dynamically generates a class at runtime that conforms to a particular interface, proxying all invocations to a single 'generic' method.
Earlier, Stellsmi asked if it's possible to do this in .NET (it's a standard part of Java). Seeing as it's the second time I've talked about it in as many days, I reckon it's worth blogging...
As far as I know, there are two ways to do this:
Using the magical RealProxy class that monkeys with the context (whatever that means). This requires that the object that is being proxied must extend ContextBound.
Using Reflection.Emit to generate a new class at runtime that overrides/implements the necessary methods and dispatches invocations to a generic handler. This can implement an interface or override any virtual method.
The first approach is pretty trivial, but it locks you into the fact that you can only proxy objects that extend ContextBound. Not ideal as this pulls a lot of stuff into your class you don't necessarily need and prevents you from inheriting something else.
The second approach is more suitable, less intrusive, but not pretty to write as it involves writing low-level IL op-codes. However, I did this already in NMock and at GeekNight, Steve and Jon lovingly decoupled the ClassGenerator from the core of NMock, so you can create generic dynamic proxies. So now it's easy to create a proxy.
Example
Here's an interface you want to create a dynamic proxy for:
interface IFoo {
string DoStuff(int n);
}
Note:
You can use one invocation handler to handle all method calls in the interface. The example above only has one method for clarity.
This doesn't have to be an interface. It could be a class, so long as the methods you want handle are all marked virtual (sigh).
You can do the same thing for properties as well as methods.
To create the proxy, you need to create an implementation of IInvocationHandler. This is called any time a method is invoked on the proxy.
class MyHandler : IInvocationHandler {
public object Invoke(string methodName, param object[] args) {
return "hello from " + methodName;
}
}
Notes:
The name of the method being called and parameters passed in are passed to this handler.
Whatever is returned by the Invoke() method is returned by the proxy.
If the method is of type void, just return null.
Finally, you need to generate the proxy itself so you can actually use the damn thing:
ClassGenerator generator = new ClassGenerator(
typeof(Foo), new MyHandler() );
IFoo fooProxy = (IFoo)generator.Generate();
string result = fooProxy.DoStuff(2); // returns "hello from DoStuff"
Ermm and that's it! Use your dynamic proxy like it's a real class.
ClassGenerator is part of the NMock library. Use it for AOP style interceptors, decorators, stubbing, mocking :), whatever.
Brain rumblings... Hmm... maybe that should be a delegate instead... maybe I should revisit some stuff...