|
From: hammett <ha...@uo...> - 2004-10-23 03:59:28
|
Guys,
I've stopped for a while to analyze our strategy on proxying concrete
classes. Just to set a common ground:
MyClass x = new MyClass()
ProxyGenerator generator = new ProxyGenerator();
StandardInvocationHandler handler = new
StandardInvocationHandler(myClass);
MyClass proxy = (MyClass)
generator.CreateClassProxy( typeof(MyClass), handler );
-=- How it works? -=-
The generator creates a dynamic type which extends MyClass and override all
methods creating stubs. These stubs code are something like:
public override void DoSomething( int val )
{
MethodInfo m = MethodBase.GetMethodFromHandle( ldtoken method );
handler.Invoke( this, m, val );
}
So every invocation has to delegate the to a "real" class instance. In the
code above, the x will be the real instance. Thus we have two copies of the
same class. Do we really need them?
The DynamicProxy originally intented to proxy interfaces, and someway it
grow offering proxy capabilities to concrete classes, but now I realize that
the interface should be different.
-=- Proposal -=-
interface IClassInterceptor // better name?
{
object Intercept( IInvocation invocation );
}
interface IInvocation
{
object[] Arguments { get; set; }
object Proxy { get; set; }
object Proceed();
}
Now the user, instead of using a IInvocationHandler, should use
ProxyGenerator generator = new ProxyGenerator();
DefaultClassInterceptor interceptor = new DefaultClassInterceptor();
MyClass proxy = (MyClass) generator.CreateClassProxy( typeof(MyClass),
handler );
Now we dont have separate instances. When a method is invoked on the proxy,
the Intercept is invoked. If the user invoke the Invocation.Proceed, the
proxy calls the super class to invoke the real implementation. How do you
like that?
-=- Under the hood -=-
I've played for five minutes, so I'm not sure if this is the best approach,
with the best performance, but it relies on delegates.
class MyClassProxy : MyClass
{
...
delegate void __MyClass_DoSomething(int x);
public override void DoSomething(int x)
{
MethodInfo m = MethodBase.GetMethodFromHandle( ldtoken method );
InvocationImpl invocation = new InvocationImpl( this, m, new
__MyClass_DoSomething(callback__DoSomething), x );
interceptor.Intercept( invocation );
}
private void callback__DoSomething(int x)
{
base.DoSomething(x);
}
}
class InvocationImpl : IInvocation
{
public InvocationImpl( object proxy, MethodInfo m, delegate call, params
object[] args )
{
..
}
public object Proceed()
{
call.DynamicInvoke( args );
}
}
Yes, it works!
But before I start to code this beast we need to agree on these interfaces.
Also, can we think of something similar to interface proxies?
We're close to the first non-beta release and once this is release, change
interfaces will hurt users, and we don't want that.
--
Cheers,
hammett
http://www.digitalcraftsmen.com.br/~hammett
|