Click here to Skip to main content
Click here to Skip to main content

Castle's DynamicProxy for .NET

By , 14 Dec 2004
 

Introduction

The proxy capabilities offered by the CLR are great. The ProxyAttribute, message sinks, and so on are really fantastic ideas leading to easy extension of the platform.

However, there are drawbacks. For example: to use proxy capabilities, your class must extend MarshalByRef or ContextBoundObject (which carries another semantic), and by doing so, you mess with your object model hierarchy. This can be very intrusive. Nevertheless, it's an option if you control the object model. But when things come from outside, there are no simple ways to achieve it.

This article explains how to use DynamicProxy, available at Castle Project, to create interceptors for your class in a fast and clean way, and yet have good performance as DynamicProxy does not use reflection to invoke the methods on the object instance.

How to use

DynamicProxy is able to proxy interfaces and concrete classes. You always have to supply the Type to be proxied and the interceptor instance. The interceptor will be invoked for each method invoked on the proxy, so you can carry on with your interceptor logic (transaction, logging, etc.) and then proceed or not with the invocation. If you choose to proceed, you must invoke the Proceed method on the invocation object supplied.

public class MyInterceptor : IInterceptor
{
    public object Intercept(IInvocation invocation, params object[] args)
    {
        DoSomeWorkBefore(invocation, args);

        object retValue = invocation.Proceed( args );

        DoSomeWorkAfter(invocation, retValue, args);

        return retValue;
    }
}

The IInvocation interface provides you with a lot of useful information:

public interface IInvocation
{
    object Proxy { get; }

    object InvocationTarget { get; set; }

    MethodInfo Method { get; }

    object Proceed( params object[] args );
}

For interfaces, you must also specify the object instance which will be the target of the invocations. Complex? Not really. Consider the following example:

public interface IMyInterface
{
    int Calc(int x, int y);
    int Calc(int x, int y, int z, Single k);
}

public class MyInterfaceImpl : IMyInterface
{
    public virtual int Calc(int x, int y)
    {
        return x + y;
    }

    public virtual int Calc(int x, int y, int z, Single k)
    {
        return x + y + z + (int)k;
    }
}

ProxyGenerator generator = new ProxyGenerator();

IMyInterface proxy = (IMyInterface) generator.CreateProxy( 
    typeof(IMyInterface), new StandardInterceptor(), new MyInterfaceImpl() );

This is a requirement as DynamicProxy needs a default target for the invocation - we'll explain why later.

Now, if you want to proxy concrete classes, there are also two requirements: the class can not be sealed and only virtual methods can be intercepted. The reason is that DynamicProxy will create a subclass of your class overriding all methods so it can dispatch the invocations to the interceptor. See the following example:

ProxyGenerator generator = new ProxyGenerator();

Hashtable proxy = (Hashtable) generator.CreateClassProxy( 
    typeof(Hashtable), new HashtableInterceptor() );

object value = proxy["key"]; // == "default"

public class HashtableInterceptor : StandardInterceptor
{
    public override object Intercept(IInvocation invocation, params object[] args)
    {
        if (invocation.Method.Name.Equals("get_Item"))
        {
            object item = base.Intercept(invocation, args);
            return (item == null) ? "default" : item;
        }
        return base.Intercept(invocation, args);
    }
}

If the class you want to proxy doesn't expose a default constructor, that's OK. You just need to supply the arguments to CreateClassProxy.

Mixins

Mixins are a kind of inheritance well-known in the C++ world. In a nutshell, the mixin-style of inheritance is the ability to mix a class with other (or others) which expose a single specific capability. DynamicProxy allows you to mix one class with others, resulting in a mixed proxy instance. If the mixins classes expose interfaces, they will be automatically exposed by the proxy instance.

public interface ISimpleMixin
{
    int DoSomething();
}

public class SimpleMixin : ISimpleMixin
{
    public int DoSomething()
    {
        return 1;
    }
}

ProxyGenerator generator = new ProxyGenerator();
GeneratorContext context = new GeneratorContext();

SimpleMixin mixin_instance = new SimpleMixin();

context.AddMixinInstance( mixin_instance );

SimpleClass proxy = (SimpleClass) generator.CreateCustomClassProxy( 
    typeof(SimpleClass), interceptor, context );

ISimpleMixin mixin = (ISimpleMixin) proxy;

Dynamic languages like Ruby are the heaven of mixins, as everything on the mixed module is exposed by the target class, but that's subject for another discussion.

Aspect# takes mixins a step further as it implements a protocol to allow the mixins instances to have a reference to the proxy instance. DynamicProxy however leaves this kind of decision up to the developer.

Under the hood

DynamicProxy generates a class on the fly similar to the following (pseudo)code:

public class ProxyGenerated : YourClass
{
  // Exposes all constructors
  
  // Overrides all methods
  
  public override int DoSomething(int x)
  {
    MethodInfo m = ldtoken currentMethod;
    IInvocation invocation = ObtainInvocationFor( deletegateForDoSomething, 
                             callableForDoSomething, m);
    return (int) _interceptor.Intercept( invocation, x );
  }

  private int BaseCallDoSomething(int x)
  {
    return base.DoSomething(x);
  }
}

As you can see, DynamicProxy relies on delegates to achieve good performance. The only performance bottleneck happens when boxing and unboxing value types. Basically, each delegate will have a pointer to another method that only invokes the base class method. This happens when you use the Proceed on the IInvocation instance.

Conclusion

For static weaving of assemblies, consider the nice and lean RAIL project. If your requirements are dynamic, consider DynamicProxy. I also need to thank all feedback and patches received through the Aspect# and Castle-devel mailing list. The users of DynamicProxy gave me the energy to refactor and tweak it time after time.

For updated information about DynamicProxy, check its site.

History

  • 13-Dec-2004 - Initial version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Hamilton Verissimo
Web Developer
Brazil Brazil
Member
Hamilton Verissimo has been working with software development for 9 years. He's involved with a lot of open source projects to fill his spare time.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
SuggestionOne thing that wasn't being covered in this article.memberNeoPunk3 Jan '12 - 0:21 
Article is good enough, but there is one thing that I didn't find and had to discover original documentation about DynamicProxies. I' talking about proxy interface with base class. In my case I used MarshalByRef class as based to publish it over .Net Remoting.   It will be nice if you...
GeneralAdding Base ClassmemberPablis23 Jul '06 - 4:37 
Is there a way to make the proxy generated from the interface to inherit from a specific class, for example from MarshalByRefObject ?  
GeneralRe: Adding Base ClassmemberHamilton Verissimo19 Aug '06 - 2:36 
That's a good idea, I'll add it to DP2 - which I'm working on.
 
hammett
http://hammett.castleproject.org
QuestionHow to test if an object is a proxymemberDavid marzo29 Aug '05 - 0:33 
Is there any way to know if an object is a proxy?   Maybe test if it has a field __interceptor Castle.DynamicProxy.IInterceptor
AnswerRe: How to test if an object is a proxymemberHamilton Verissimo29 Aug '05 - 6:16 
Hi The NHibernate team makes the proxy implement a marker interface so they can check later whether the instance is a proxy or not.   -- Cheers, hammett http://www.castleproject.org/~hammett
GeneralLight weight proxymembercklein12 Apr '05 - 5:58 
I know this dynamic proxy provides a lot more, but if I only want to proxy an interface, I can just use the tranasparent proxy build in .NET.   Now I am wondering on performance wise, which one will perform better?
GeneralNice ideamemberRüdiger Klaehn24 Feb '05 - 7:18 
I did something similar in this and this article.   One thing I don't understand is how dynamic proxying for classes works. You generate a proxy that inherits from the type that is to be proxied and overrides all virtual methods.   But in order for this to work you have to create...
GeneralRe: Nice ideamemberHamilton Verissimo24 Feb '05 - 7:24 
Hello,   There is not two instances when proxying concrete classes. The user ask for a proxy and do not supply a instance itself. DynProxy generates a type that extends the specified type, as you said. Next it instantiates the new type and returns the instance.   The new type also...
GeneralRe: Nice ideamemberRüdiger Klaehn24 Feb '05 - 8:18 
OK, I understand. My proxy generators generate proxies for existing objects, so they would have to generate a second object.   I like the mixin support, but there should be a shorter way to use this. Maybe like this:   class A { void MethodA() { Console.WriteLine("A");...
GeneralRe: Nice ideamemberPortatofe2 Oct '08 - 5:20 
Thanks for share us the great Archive!   Cake Shop Cooking Dash Lost Secrets: Bermuda Triangle Cinema Tycoon 2: Movie Mania The Hidden Object Show: Season 2
Generalsuggest adding a link to a FAQ, better yet simple code examplesmemberBillWoodruff21 Dec '04 - 0:49 
While I am sure this may be a valuable contribution, the general practice in CodeProject, imho, is to provide working code with the article that illustrates what the article talks about, or on which the article is based.   I'm simply not familiar with these development methodologies, but...
GeneralRe: suggest adding a link to a FAQ, better yet simple code examplesmemberHamilton Verissimo27 Dec '04 - 6:26 
Certainly. But I think the samples in this other article depicts the functionality of DynamicProxy:   Thanks,   hammett
AnswerRe: Got example of what this is good for?memberbeardman14 Dec '04 - 22:21 
Logging: consider how easy it would be, using this methodology and logging compoments such as log4net, to make an application that could log every method called, and the parameters passed to it.   Doing it this way, using a Dynamic Proxy, would be far less work than having to put code in...
GeneralRe: Got example of what this is good for?memberRipplingCreek1 Dec '06 - 11:02 
You mean like this? http://www.jetbrains.com/profiler/[^]
QuestionGot example of what this is good for?memberronnyek14 Dec '04 - 5:17 
I am not opposed to posting information on products etc, espectially ones that appear to be free/opensource...   I just fail to see what use this dynamic proxy is good for? You have an example of any kind?
AnswerRe: Got example of what this is good for?memberHamilton Verissimo14 Dec '04 - 6:49 
Well, NHibernate, iBatis.Net and others are using it to deliver lazy load capabilities to object models.   Aspect# implements AOP with it.   hammett
GeneralRe: Got example of what this is good for?memberronnyek14 Dec '04 - 6:52 
ahh exactly what I was looking for... now I understand completely.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 14 Dec 2004
Article Copyright 2004 by Hamilton Verissimo
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid