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 |