Ramkishore wrote: > In Java, proxies may be created only for only those classes > that implement atleast one interface to make them transparent > by typecasting to the interface.
The use of interfaces means that code that uses the proxy doesn't care what the underlying type is. This makes it easy for a dynamic proxy to be plugged in. To be able to support dynamic proxy-like behaviour with classes rather than interfaces requires support from the VM/CLR. The CLR has such support, although it has its limitations, as you are aware: > Now, I know that similar functionality can be acheived by rolling > my own extension to RealProxy at the cost of classes extending from > ContextBoundObject and the overhead of method stack ->IMessage > conversion made by TP that I prefer to avoid. So it's the cost of building the message that you wish to avoid? (And by the way, you should only need to extend MarshalByRefObject shouldn't you?) > One solution that will work is to have the Dynamic Proxy class > that is built at runtime using Reflection.Emit to extend the type of > the class to be proxied. But that limits only virtual methods to be > intercepted by the Proxy. Now since CLR works out the magic of > type-related operation(GetType, typecasting, isinstance check, etc...) > and interception of virtual and non-virtual method invocation on TP, > I thought my dynamic proxy implementation can leverage those features > using TP and by overriding TP's behaviour (of method call -> IMessage > conversion followed by subsequent RealProxy.Invoke(IMessage) method > call) to invoke my DynamicProxy implementation with a different > signature. Ah, I think I understand now. So you're observing that the CLR can generate code in such a way that all calls into a MarshalByRef object can be intercepted, but you would like the interception code to do something different from building a message object. Specifically, you are happy to supply methods that have the necessary signature to handle the call directly, instead of needing the parameters to be turned into a message object? I've had look through the Rotor source code for this to see what it does here. This is not always a sure fire way of working out what the real CLR does, because although they are related codebases, the CLR evolved quite a lot after the Rotor codebase was forked. But it might still shed some light. In Rotor, the actual code that gets executed when you call into a virtual method on a TP is generated by the CTPMethodTable class's CreateThunkForVirtualMethod. (There's another method that generates non-virtual thunks.) You can see where these methods get generated here: http://plaswww2.fit.qut.edu.au/RotorWiki/i386_2remotingx86_8cpp-source.h tml#l00101 Anyone who ever used Keith Brown's Universal Delegator back in the COM days will find the generated code instantly familiar - it pushes an index onto the stack (the index into the virtual function table) and then calls to a handling function referred to as the 'entry point'. One thing to bear in mind here is that it looks rather like all of this is generated statically, i.e. *all* proxied instances share a single virtual method table (and hence the same entry point). This is perfectly reasonable - you don't necessarily need one per type (and certainly not one per instance) because you can always obtain context from the this reference (which is always in ECX). It's a little hard to follow, and maybe someone who knows Rotor better than I do will jump in and correct me here, but it does look like the first thing this 'entry point' code does is to call whatever the 'stub' you passed in was. It uses a CALL, so your stub is expected to return, and if it returns anything other than 0, this seems to be handled as a 'context mismatch'. I'm guessing here that this is used to cause the use of interception. (So this code usually just makes the 'Intercept vs. pass through' choice, if my guess is correct.) So I guess that in principal you could put your own code in here. The problem is that it will of course be the same code every single time... Now that's not necessarily a problem - if you go looking far enough up the stack you'll find the slot index, which in principal allows you to work out which method was called, and handle it appropriately. And of course you can monkey with the stack frames, and skip out the code that would normally run after the stub, returning directly to the original caller. But all of this will be horribly non-portable. It's not clear how you're supposed to find out what the index will mean - mapping of index numbers onto specific method names may not remain the same from one version of the CLR to the next. It's not clear that the stack frame will be set up in the same way from one version to the next. And anything you do with this definitely won't work on other processors, such as the Itanium. (Well...not unless you're running in 32 bit mode.) There's also the fact that the system pretty much expects the stub to return. It either returns 0, in which case interception doesn't happen as far as I can tell, or it returns non-zero, in which case the call is forwarded to the RP. While it looks like you would probably get away with just messing with the stack pointer to subvert the remainder of the call, it again doesn't inspire confidence... So you might be able to get it to work as an experiment, but I would strongly recommend against ever doing anything like this in production! > If so, does the stub point to an array of IL code generated > using Reflection.Emit() or is it a pointer to JIT'ed machine > code? It points to x86 code. I'm not sure whether it is normally JITed machine code, or just part of the normally-compiled code that makes up the CLR. It might be difficult to make it normally JITed code if you wanted access to the parameters, because of the need to be able to do stack magic - because this is a single entry point used for every single virtual method (assuming I've browsed through the Rotor code right) it needs to dynamically decide what it's call frame should look like on the fly. I don't think the JITer generates code that works like that. As far as I know none of this is documented at all, which is the real problem. -- Ian Griffiths DevelopMentor > -----Original Message----- > From: Ramkishore [mailto:[EMAIL PROTECTED] > > Griffith, > > Thanks for your explanations to my query. Sorry, I should have been more > specific about what I am trying to acheive, in my earlier posting. > > Anyways, what I am getting at is developing a Java like Dynamic Proxy > equivalent in .NET for any class type. In Java, proxies may be created > only > for only those classes that implement atleast one interface to make them > transparent by typecasting to the interface. In my quest for a more > flexible > solution in .NET compared to the Java approach, I attempted writing a > Dynamic Proxy in .NET similar in lines to the TransparentProxy equivalent. > Now, I know that similar functionality can be acheived by rolling my own > extension to RealProxy at the cost of classes extending from > ContextBoundObject and the overhead of method stack ->IMessage conversion > made by TP that I prefer to avoid. One solution that will work is to have > the Dynamic Proxy class that is built at runtime using Reflection.Emit to > extend the type of the class to be proxied. But that limits only virtual > methods to be intercepted by the Proxy. Now since CLR works out the magic > of > type-related operation(GetType, typecasting, isinstance check, etc...) and > interception of virtual and non-virtual method invocation on TP, I > thought > my dynamic proxy implementation can leverage those features using TP and > by > overriding TP's behaviour (of method call -> IMessage conversion followed > by subsequent RealProxy.Invoke(IMessage) method call) to invoke my > DynamicProxy implementation with a different signature. > > My question is whether the "stub" parameter of type IntPtr in the > constructor of RealProxy is provided for achieving this flexible override > behaviour. If so, does the stub point to an array of IL code generated > using Reflection.Emit() or is it a pointer to JIT'ed machine code? > > Thanks, > Ramkishore > > > ----- Original Message ----- > From: "Griffiths, Ian" <[EMAIL PROTECTED]> > > > I'm assuming here that you're using "stub" in the Java sense, to mean > the thing on the client side that looks like the object. (Microsoft > have always used "stub" to mean the other end. They use the term > "proxy" for the client-side part. But the only way I can make sense of > your post is if you mean the client-side part when you say "stub".) > > If what you want to do is control the signature of the methods > available, then you don't need to write your own TP. All you need to do > is build a transparent proxy for a type which supplies the signatures > you require. > > If you already have an appropriate interface definition or class > definition defining the method signatures you require, then you're done. > But if you would like to generate method signatures at runtime, you > should be able to generate the interface definitions using > Reflection.Emit, and then pass the resulting generated type in when you > build the Transparent Proxy. > > So you really don't need to be able to generate the TP yourself to > achieve what you're trying to achieve. (Which is a good thing - you > wouldn't be able to do so reliably anyway, because there's no guarantee > that the calling convention used by the CLR won't change from one > version of .NET to the next. Using this approach insulates you from > such changes, and also means it should work on the Itanium version of > .NET, whenever that appears.) > > > But if you really do mean stub in the Microsoft sense (i.e. the bit on > the server side), you can replace absolutely anything downstream of the > transparent proxy, and you don't need assembly language to do it. > > -- > Ian Griffiths > DevelopMentor > > > -----Original Message----- > > From: Ramkishore [mailto:[EMAIL PROTECTED] > > > > Hi, > > > > Does anyone know how to write a custom stub for the TransparentProxy/ > > RealProxy. RealProxy constructor does take in a stub of type IntPtr. I > > would like to know if there is any way to control the method signature > > invoked by TransparentProxy. My understanding after reading Chris > Brumme's > > blog http://blogs.gotdotnet.com/cbrumme/ on TransparentProxy is that > the > > stub is a machine code.(ie. x86 code for windows). If so, I guess > there > > is no portable way to provide our own stub implementation, right? =================================== This list is hosted by DevelopMentorŪ http://www.develop.com NEW! ASP.NET courses you may be interested in: 2 Days of ASP.NET, 29 Sept 2003, in Redmond http://www.develop.com/courses/2daspdotnet Guerrilla ASP.NET, 13 Oct 2003, in Boston http://www.develop.com/courses/gaspdotnet View archives and manage your subscription(s) at http://discuss.develop.com