Castle Dynamic Proxy FAQ: why there’s no “class proxy with target”

One of the commonly asked questions about Castle Dynamic Proxy:

How do I use CreateClassProxy to wrap an existing object to intercept calls to its virtual members?

Short answer is – you can’t. And if you think about it, there’s a very good reason for that.

Since classes are stateful, and there's no requirement that all their members are virtual, you could end up with inconsistent state, where part of the state comes from proxy object, part comes from the target object. This would lead to bizarre behavior and bugs, that would be hard to catch. For that reason Dynamic Proxy does not expose this functionality.
You can either expose the required set of API as interface and create interface proxy with target interface, or to create a wrapper class.

Example

If that’s not clear enough, consider the following example of how such proxy could look like and behave:

class Program
{
    static void Main(string[] args)
    {
        var joe = new PersonImpl(17);
 
        Debug.Assert( joe.IsAdult() == false );
        var proxy = new PersonProxyWithTarget( joe );
        Debug.Assert(proxy.IsAdult() == false);
        proxy.HasBirthday();
        Debug.Assert(joe.IsAdult() != proxy.IsAdult()); // <- we have an issue here
    }
}
 
public abstract class Person
{
    protected int age;
 
    public abstract int HasBirthday();
 
    public bool IsAdult()
    {
        return this.age >= 18;
    }
}
 
public class PersonProxyWithTarget : Person
{
    private readonly Person target;
 
    public PersonProxyWithTarget(Person target)
    {
        this.target = target;
    }
 
    public override int HasBirthday()
    {
        CallInterceptors();
        return target.HasBirthday();
 
    }
 
    private void CallInterceptors()
    {
        //calls interceptors
    }
}
 
public class PersonImpl : Person
{
    public PersonImpl( int age )
    {
        this.age = age;
    }
 
    public override int HasBirthday()
    {
        return this.age++;
    }
}

As you can see here, we have a class which has some state in it. We then create a proxy, and call some methods. The important thing is the last assert. Proxy returns invalid results to us – we have a bug! While the proxy should be transparent, and behave as if it was the joe himself, it returns false values to us. This is not something that can be worked around, hence no class proxies with targets.


Posted 12-02-2009 5:14 PM by Krzysztof Koźmic
Filed under:

[Advertisement]

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)