Geeks With Blogs
Greg Young Greg.ToString()

In the creation of my dynamic proxy I ran into some “interesting” fringe conditions....

I started off as all do needing a very simple interceptor generator, this is btw very easily done if anyone is thinking about attempting it. I later decided to add mixin support which was a bit more interesting. That said lets get into some background information to help explain the issues.

Mixins for those who are not aware involves the dynamic aggregation (either at compile, link, or runtime) of multiple objects. When I first did mixins I only supported interface/implementor pairs (I'll explain why after the example). Here's a basic hand done example of what occurs when we are implementing an interface/implementor pair.

public class BasicClass {
public virtual int Method() {
Console.WriteLine("BasicClass:Method");
return -1;
}
public BasicClass() {}
}

 

public interface IBar {
    void Go();
}
Our implementer
public class BarImplementer : IBar {
    public void Go() {
          Console.WriteLine(“BarImplementer::Go”);
    }
}
 
and finally the aggregation class that would be generated to show the “mixin“ behavior
 
 
public class BasicClassWithIBarProxy : BasicClass, IBar //inherit from our subject and add interface  {
private BasicClass m_Subject; //encapulate our subject
private BarImplementer m_Bar; //encapsulate our implementer
//override method and broker the call to our subject.
public override int Method() {
Console.WriteLine("BasicClassProxy:Method");
return m_Subject.Method();
}
public void Go() { //needed for IBar
                    m_Implementer.Go();
       }
//allow our subject to be given to us upon construction
public BasicClassProxy(BasicClass _Subject, BarImplementer _BarImplementer) {
m_Subject = _Subject;
}
}
 
To make this generic one could say that my dynamic proxy generation went through the following steps
 
 
  • Iteratre through interface implementor pairs
  • Add interface to class declaration
  • add parameter to constructor
  • encapsulate the class
  • iterate through the methods of the interface adding method redirection to encapsulated implementor
  • iterate through each event creating a quick handler that bubbles the event
 
As one can see the generated class is simply a proxy of BasicClass that also aggregates IBar passing the method calls off to an implementor object who knows how to handle the calls received for IBar. You will notice that in this case I am not passing context, I did this for simplicity of the example the real server does pass context information to the implementor. This is a wonderful way of performing my aggregations but as I knew would happen I ran into a case where the code that I needed to aggregate was not mine nor did it support an interface. I at this point decided to support multiple base class base aggregation.
 
I am quite sure the astute reader just thought “wait this is a single inheritance based environment“. Well actually the very astute reader probably knows that there are numerous simulated multiple inheritance patterns available :) I chose to use David Esparza-Guerrero's pattern listed here http://www.codeproject.com/csharp/smip.asp to do my simulated multiple inheritance. To make a long read short (though I recommend reading it)... it uses implicit operations to allow for the simulation. Note that this aggregation based method only supports public contract MI not true MI within the object itself (although with a bit of hacking with reflections to avoid scope issues ... actually just no ... don't do that :))
 
Using such a methodology becomes a _bit_ more interesting as we are not assured to be successful every time! The major culprit here is public variables (the astute reader may also point out that non-virtual methods also are a problem). Public variables are a nightmare because there is no way of intercepting them to pass through the call to the subject object. While its quite easy to say “use properties“ it is more difficult in practice when you do not necesarily know what you will be operating nor will you control everything you operate on. Due to this I decided to take a best stab at it.
 
The first bit that I added was detection if the subject classes had public variables, this helped alot by throwing them out immediately I would allow the base (primary subject) to have public variables but not the mixins ...
 
And finally ...
 
We are to my fringe cases!
 
What if multiple classes have public variables?
Barf an error
 
What if the base class did NOT have public variables but one of the mixins did?
 
Well I supported it, my code at this point will actually change out the subject to be the mixin that has public variables and will treat the original class to be proxied as if _it_ were a mixin, externally the behaviors are the same.
 
What if the classes have non-virtual methods?
 
Well I just complain about it I still generate the class but I generate messages ...
 
 
I would love to hear some general thoughts from other people who have dealt with the same issue and their methods of handling this.
 
Cheers,
 
Greg
Posted on Tuesday, January 24, 2006 12:25 PM AOP | Back to top


Comments on this post: Dynamic Proxy Quandries

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Greg Young | Powered by: GeeksWithBlogs.net