How to do Dynamic Proxies in C#

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.

h3. 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…

  • Trackback are closed
  • Comments (14)
    • Anonymous
    • February 12th, 2004

    I thought there was some kind of Code DOM in .NET that lets you define and compile code without having to fiddle with byte codes.

    • Joe Walnes
    • February 13th, 2004

    Yes there is, but there’s a high overhead in invoking the compiler each time you want to create a new proxy, so I didn’t consider it.

    • Stefan Zobel
    • February 13th, 2004

    Great work! I started to implement this myself last year since it is such a useful functionality to have (I always wondered why Microsoft missed this in the .NET Framework). Could you please supply a source distributon of NMock on sourceforge? Personally, I prefer to browse the code locally and I hate working with CVS remotely.

    Regards, Stefan

  1. I gotta look into C# a little further. It looks pretty cool!

  2. Another Reflection.Emit approach is what I did in Chapter 8 of my CIL book. You can get the code here:

    http://www.apress.com/book/supplementDownload.html?bID=88&sID=525

    Regards,

    Jason

  3. This is really neat:)
    I like the improvement that you can do dynamic proxies for classes.
    I’ve previously made a short article about how to do a dynamic proxy using the RealProxy for those interested in learning more about that approach:
    http://www.codeproject.com/dotnet/dynamicproxy.asp

    /Jeppe

    • Seb
    • February 16th, 2004

    Hi,

    I wrote an article (in french) about Reflection.Emit proxies (simulates the Java way of doing it), along with full source code that should be in english

    Check it out at :
    http://www.dotnetguru.org/articles/dossiers/instrumentation/proxiesdynamiques.htm

    -S

    • Gilles
    • March 3rd, 2004

    Your solution don’t work for an ‘Arraylist’ proxy, see below, there’s a bug on the Add(5)

    ClassGenerator generatorList = new ClassGenerator(
    typeof(ArrayList), new MyHandler() );
    IList listProxy = (IList)generatorList.Generat();
    listProxy.Add(5);

  4. Joe,

    This is exactly what I’ve been looking for I’ve tried a few differnent approaches to implement AOP intercepters, Code DOM (but I don’t want to write a parser or recompile the code), Real Proxys (but I don’t want all objects to be ContextBound) or Reflection.Emit (I don’t want to learn IL) Sounds like you done the leg work for me.

    Thanks

    • Jack
    • March 21st, 2004

    Joe – FANTASTIC WORK. Gilles mentions a bug above. Is this fixed?

    Seb – have you considered translating your article to english?

    • Toney Alguire
    • March 21st, 2004

    Nice work, but there is a flaw that should be removed.

    In java, a reference to the object on which the proxy is called is passed to the invoke method as the first parameter. This is extremely useful and actually required by several application I’ve been working on in java.

    One example is when the creation process associates data with the instance (such as an database OID). But there is no way of getting the instance from the proxy.

    Could you elaborate about how to extend the ClassGenerator class to support this functionality?

    • exortech
    • April 1st, 2004

    btw, you don’t need to extend ContextBoundObject to do interception using RealProxy. you can extend MarshalByRef instead. it is much more performant than CBO, and plus, you are more likely to have a use for MBOs when using remoting. makes building interceptors for remote objects quite easy.

  5. Hi,

    the article mentioned in my previous post gave birth to a gotdotnet workspace at http://workspaces.gotdotnet.com/dynaprox

    Fell free to join !

    -S

    • Poli
    • May 15th, 2006

    What about Castle Dynamic Proxy ??? http://www.castleproject.org/index.php/DynamicProxy

Comments are closed.
%d bloggers like this: