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

Reply via email to