From: hammett <ha...@uo...> - 2004-10-25 06:12:21
|
Hello dudes, After a few hours (ok, several) and now almost able to write a book about IL programming, I finally finished the DynamicProxy refactory. What changed? == Interface proxy == Dynamic Proxy still able to proxy interfaces, but the public interface changed from proxygenerator.CreateProxy( Type, IInvocationHandler ) to proxygenerator.CreateProxy( Type, IInterceptor, object target ) The target is null or what implements the interface being proxy. The IInterceptor interface follows public interface IInterceptor { object Intercept( IInvocation invocation, params object[] args ); } (I know, from a OOP PoV the IInvocation should store the arguments too, but this usage allows us to cache the invocation instance) A StandardInterceptor is provided to make things even simpler. == Concrete classes proxy == The public interface changed from proxygenerator.CreateClassProxy( Type, IInvocationHandler ) to proxygenerator.CreateClassProxy( Type, IInterceptor ) == Under the hood == While little changed in the public interface, a lot changed in the generated code. Inspired by how boo deals with closures (http://boo.codehaus.org) I've created an ICallable interface which is implemented by nested delegates in the proxy class. The eq. C# code would be something like class MyClassProxy : MyClass { public sealed class _Delegate_Do_1 : MulticastDelegate, ICallable { public _Delegate_Do_1(object target, intptr methodoffset) {} public void Invoke(int x, int y) {} public virtual object Call( params object[] args ) { this( (int) args[0], (int) args[1] ); // Invokes the delegate } } public MyClassProxy( IInterceptor interceptor ) : base() { this.interceptor = interceptor; } public override void Do(int x, int y) { MethodBase m = MethodBase.GetMethodFromHandler( ldtoken m ); IInvocation invocation = _Method2Invocation( new _Delegate_Do_1(callback_Do), this, m ); invocation.Intercept( invocation ); } private void callback_Do( int x, int y ) { base.Do(x, y); } } This allows an elegant invocation.Proceed() to invoke the base method or the interface implementation. The performance should be very good, better than it was as there is _no_ invocation through reflection anymore. :-) == Serialization == The GetObjectData is partially implemented, and the ProxyObjectReference is capable of recreating the proxy instance. What is left to be solved (I need to sleep right now zzz) - The GetObjectData implementation should (somehow) be able to persist the fields of the super class (need to stop to think about it carefully) - The GetObjectData should save a type array of interfaces implemented by the proxy - The GetObjectData should invoke a virtual method passing the ILGenerator along, allowing augmenting it easily All of this impact Aspect#, that need to be refactored as well. I plan to do it this very week. Suggestions are welcome! Night! -- Cheers, hammett http://www.digitalcraftsmen.com.br/~hammett |