|
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
|