Geeks With Blogs
Greg Young Greg.ToString()

As some of you may have realized, I am in the process of re-implementing my AOP framework to fully support generics right now (figured I might as well as I am white boarding it for open source deployment anyways). I have come across numerous issues in dealing with generics. Today I sent an email to the castle project group (who are going through a similar task in supporting generics in Dynamic Proxy). I figured I would post that email here as well in case others have thoughts on some of the issues I present.


I am going to dump out some of my experiences here, I have already shared some of these with hammett off list but they may help in the design of the next version of dynamic proxy (and definitely bring up discussion points).
 
The goal of truly supporting generics is the ability to reuse the generic proxy. This goal is not easily realized, I am beginning to question whether or not it is even worthwhile to create generic proxies.
 
Interceptors:
 
In order to have a functional generic dynamic proxy system I need to support generic aware point cuts.
 
Foo<T>.SomeMethod .. applies to all proxy instances
Foo<SomeClass>.SomeMethod .. only applies to proxy instances where T=SomeClass
Foo<T>.SomeMethod where T is ISomething .. dynamic application where T implements ISomething
 
This makes generation of generic proxies nasty at best. If we want to build a reusable proxy we have to build a superset of all defined behavior for any derived versions then conditionally not do anything at those interception points. We can move this behavior out to our interceptor cache ( i.e. simply pass a better context and return null representing no action to be taken) but this is still placing code into our proxies that we know for a fact will never be used.
 
ex:
 
an after interceptor defined only on Foo<int> must be placed on Foo<T> and checked in an if for all other classes .. This would allow us to reuse the generic proxy but has a trade off of performance for the other proxies.
 
This problem becomes compounded when dealing with mixins as someone could define a mixin only to apply to Foo<SomeClass> and not to Foo<T>. As such our previous solution of managing this in an interceptor cache becomes invalid so we are forced to create separate proxies for closed types in many cases. This will alleviate the problem of having garbage interceptor code but now we are also losing the ability to reuse our generic proxy.
 
This also adds a level of complexity to the cache. When given a Foo<SomeClass> you would first look in the cache for a Foo<SomeClass> .. if Foo<SomeClass> did not exist you would then have to analyze the metadata defining any aspects for Foo<SomeClass> to determine if you could use Foo<T> instead or whether you needed to generate a specific Foo<SomeClass> proxy. Providing we only ever _ADD_ behavior to a proxy we could reuse the open type proxies by inheriting from them for the more specific proxy having the inherited proxy adding further functionality to the base proxy ... This becomes interesting as for interceptors it may or may not add interception points meaning we have to inspect heavily the metadata in order to determine whether or not we actually need to create a subclass or whether we are simply receiving different interceptors at the same locations (easy operation but kind of annoying)
 
Of course to do things right you would want an operation that could also REMOVE an interception, example I want to add an interceptor to add on all List<T> except for List<MyUseVeryOftenClass> ... this operation obviously makes inheritance a bit more tricky.
 
Another issue I have come across in dealing with generic mixins is the following situation.
 
public class A<T,V> {}
public interface B<T,V>{}
public class Bimplementor<T,V> {}
I want to mixin B with A though BImplementor .. when I go to generate my proxy there are two related issues.
 
1) Are T,V pointing to the same thing? :)
2) If not what should B's T,V be... I need some way of being given this metadata
 
they have defined .. (in some fictitious language that I will use through out this)
Class A<T,V> mixin B, BImplementor<A, B>
 
My proxy would need to be defined something similar to the following ..
 
public class AProxy <T,V,A,B> : B<A,B> {
}
 
because the T,V does not match up .. when I go to create an instance of this proxy I need to know what to put into A and B as they will not be provided. One could quite easily force a closed definition in the aspect definition i.e.
 
Class A<T,V> mixin B, BImplementor<int, double>
 
which would help many of these issues
 
The flip side of this is if we want them to match up (i.e. we want to reuse the same parameters of the original class)
 
public class AProxy<T,V> : B<T,V> {
}
 
perhaps an aspect definition similar to
 
class A<T,V> mixin B, BImplementor<T,V>
 
But there should also be a fair amount of error handling to insure that all values of T and V are in fact valid for A and B of the related interface
 
I guess the real point I am trying to make is that there are all sorts of fun conditions where we end up just using a closed proxy anyways .. How often will we really get to use an open proxy, are the times that we can use them worth all of the complexity? Similar behaviors could have been had in 1.x by allowing inheritance within definitions (and inheriting proxies) but I have yet to see an implementation that did this .. ex:
 
Class A mixin B, BImplementor
 
applies not only to A but all classes that inherit from A
 
 
 
In my particular case I have even further problems because I support multiple non-pure base class aggregation with a pattern similar to this http://www.codeproject.com/csharp/smip.asp . The additional problem here is that while A<T> and B<T> may have no public fields (I therefor inherit from A<T>) .. I may run into a point where B<T> ends up having a public field later on (as such I would need to inherit from B<T> and aggregate A<T> in order to support the public fields)
 
Just some food for thought :)
 
Cheers,
 
Greg


Posted on Monday, May 29, 2006 1:02 PM AOP | Back to top


Comments on this post: AOP with Generics Thoughts

# re: AOP with Generics Thoughts
Requesting Gravatar...
Post very nicely written, and it contains useful facts. I am happy to find your distinguished way of writing the post. Now you make it easy for me to understand and implement. Thanks for sharing with us.
Left by Mcx Tips Trial on Nov 18, 2010 3:40 AM

Your comment:
 (will show your gravatar)


Copyright © Greg Young | Powered by: GeeksWithBlogs.net