Joe Walnes
  Blog



Recent Entries

Creative uses of Hamcrest matchers

Hamcrest 1.1 released

Testing on the Toilet

Building testable AJAX apps (Does my button look big in this?)

QDox is back - 1.6 released

Java and .NET RESTful interoperability with XStream

I've joined Google

OSCon: SiteMesh, SiteMesh, SiteMesh, SiteMesh

Flexible JUnit assertions with assertThat()

SiteMesh and Content Management @ O'Reilly OpenSource Conference

XStream 1.1.2 released. Java 5 Enums, JavaBeans, field aliasing, StAX, and more...

VB.Net is the bestest

XStream 1.1.1 released

Accessing generic type information at runtime

XStream 1.1 released

JUnit tip: Setting the default timezone with a TestDecorator

XStream: how to serialize objects to non XML formats

How my backflip went...

Backflippin' in 4 hours.

Is 100% test coverage a BAD thing?

Looking back at the SiteMesh HTML parser

The road ahead for SiteMesh 3

Joe's Backflipping for Autistic Research - time is nearly up...

SiteMesh 2.2 Released

Advanced SiteMesh

More... [RSS | RDF]

About Joe Walnes

I am a software engineer for Google, based in London.

Open Source

WebStuff (coming soon)

XStream

ActiveMQ

SiteMesh

QDox

nMock

jMock

Pico Container

Nano Container

OpenSymphony

Squiggle

MockDoclet

MockObjects

Jelly

Groovy

PatternStitcher

XJB

Books

Java Open Source Programming, Wiley JSP Site Design, Wrox

Talks

Mock Roles, not Objects
October 26 2004, Vancouver, Canada. OOPSLA'04

Personal Development Practices Map
June 24 2004, Salt Lake City, Utah. Agile Development Conference

SiteMesh.NET and ASP.NET MasterPages
May 20 2004, Bangalore, India. Bangalore .NET User Group

Mock Objects: Driving Top Down Development
March 29 2004, St Neots, UK. OT2004

Mock Objects
December 2 2003, London, UK. XP Day 3


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 <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRuntimeRemotingProxiesRealProxyClassTopic.asp
    ">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...

Comments

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

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

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

homer jay

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

Jason Bock

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

Jeppe Cramon

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

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

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);

Chris Brown

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

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

Seb - have you considered translating your article to english?

Toney Alguire

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

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.

Seb

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

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

standard chair lose or not

Nice post. I'll return. faithful, central, astonishing nothing comparative to tremendous

international round do or not

Your site is exactly the kind of sites which make the net surfing so fun. to fetch opponents you should be very universal

Britney

Hello, nice site look this:
Cyrus Broacha

End ^) See you

Hillary

Hello, nice site look this:
Cyrille van Hoof

End ^) See you

Britney

Hello, nice site look this:
Cyrille Carreon

End ^) See you

Dwayne Johnson

I love this site, there is so much information to be found. Thank you.
Dwayne Johnson

no consultation

intercepting plasterer detains cremations!singsong testifying protruded:torturing

Poorret

[URL=http://blow-job-clip.ubmission.cn]blow job clip[/URL]

Poorret

[URL=http://teacher-fucking.tsukishima.cn]teacher fucking[/URL]

Name:
Email:
URL:

ThoughtBloggers

Martin Fowler

Dan North

Aslak Hellesoy

Darren Hobbs

Geoff Oliphant

Mike Roberts

Chris Stevenson

Jon Tirsen

Loads More...

Agile Bloggers

Ken Arnold

Ward Cunningham

Brian Marick

Robert Martin

Bret Pettichord

Java Bloggers

Ara Abrahamian

Mike Cannon-Brookes

Vincent Massol

Bob McWhirter

Rickard Oberg

Joseph Ottinger

James Strachan

Hani Suleiman

Communities

eXtreme Tuesday Club (XTC)

Thursday GeekSpeek

ThoughtWorks GeekNight

London Java Meetup

The Codehaus

[RSS | RDF]
© 2001-2004, Joe Walnes

Powered by SiteMesh and Moveable Type.