Link to home
Start Free TrialLog in
Avatar of eventprostrategies
eventprostrategies

asked on

.NET Remoting (Passing COM+ RCW Possible?)

I've just about given up - I think I'm going to have to scratch my current data flow architecture for my up-coming project and start over.  Here's what I'm generally getting :

          "InvalidCastException: Return argument has an invalid type"

And I'm not sure if I'll be able to get past it.  Some of the objects that I need to pass are objects in an interop assembly (a vendor's API) that's generated from VB6 --> tlbimp --> .net DLL rcw (runtime callable wrapper).  Here's the problem - I can't set any of those objects to serializable, because I can't change the code, so what can I do?  I've thought about making managed wrappers for all of the objects and I still might ... here's what I *WANT* to do:

[APPLICATION] ---> (calls your own registered assemblies via OLE Automation) ---> [MyOLEHook : IWhateverInterfaceIsRequiredForTheHook]

Now, I have a number of these OLE Hooks and I don't want any of me 'real' code here - i want to use these as proxies.  Currently, this is what happens:

[MyOLEHook.SomeTriggeredMethod(string str1, OleObject obj1)]
{
    RemotingClientClass client = new RemotingClientClass();
    client.ConnectToServer();
    IWhateverInterfaceIsRequiredForTheHook realHook = (IWhateverInterfaceIsRequiredForTheHook) client.GetRealHookFromServer("IWhateverInterfaceIsRequiredForTheHook");
    realHook.SomeTriggeredMethod(str1,obj1);
}

...

what I have set up now works GREAT for passing along any .NET managed & serializable object that both the client and server assemblies have references to, but I haven't been successful in passing COM objects.  is it possible at all?  or will i have to do this, instead : (?)

[MyOLEHook.SomeTriggeredMethod(string str1, OleObject obj1)]
{
    RemotingClientClass client = new RemotingClientClass();
    client.ConnectToServer();
    IWhateverInterfaceIsRequiredForTheHook realHook = (IWhateverInterfaceIsRequiredForTheHook) client.GetRealHookFromServer("IWhateverInterfaceIsRequiredForTheHook");
   
    OleObject1Managed mgd1 = new OleObject1Managed(obj1);

    realManagedHook.SomeTriggeredMethod(str1,mgd1);
}

-------------

now, for those of you who're asking WHY i don't just implement the code in the hook that the application calls ... here's why.

1) the assemblies that act as hooks for the application need to be registered and they need to have certain names and ... they're just not fun to work with.
2) plugin-architecture.  the way that I have things set up now (if the COM objects would pass along Remoting) ... I have a customized application which loads ... finds all of the implementations for these various hooks (there could be many for each hook) ... you can select your 'Active' implementation of any one of the hooks and change them at any time, effective immediately ... and the hooks can be named whatever I want, so long as they implement certain interfaces.  I don't like vendors' APIs denormalizing my code - I'd rather set something up on the vendor application side that I can talk to however I want to and in a managed environment.

So -- does anyone know of any tricks I can use to be able to pass objects from a library created with tlbimp along Remoting channels?  *OR* do you recommend a good way of wrapping them?  Should they be wrapped like ...

1? : class OleObject1Managed : OleObject1Class

2? : class OleObject1Managed : OleObject1 (this is an interface - this is what tlbimp does when you run it against an assembly ... it makes ClassName interfaces and ClassNameClass classes)

3? : class OleObject1Managed
      {
           protected OleObject1 _innerOleObject1;
           public OleObject1 InnerOleObject1
           {
               // getters setters
           }
      }

4? : class OleObject1Managed
      {
           public OleObject1Managed(OleObject1 oleObject)
           {
               // set properties of managed class based on OleObject1 ... but this doesn't allow for methods, etc, which isn't acceptable.  We need to be able to ue the object's methods.
           }
      }

---------------

I could really use some advice on this one!  Given the amount of development time spent on this ... I'll probably make wrappers of some kind if I can make them work.

What do you guys think?  TIA
Avatar of eventprostrategies
eventprostrategies

ASKER

Source Code (wo. NAnt) : http://www.remitaylor.com/dev/RemotingRover.zip (156 KB)
Source Code (w. NAnt) : http://www.remitaylor.com/dev/RemotingRover_NAnt.zip (4.52 MB)

I found the following bit** that made me think that dealing with RCWs in Remoting shouldn't be a big deal.  Now, the source I'm showing isn't my real source (corporate - no can do), and it isn't throwing the Invalid Type error but it is having some issues and i built it JUST for EE so you can have a look at the architecture and see if you can make it work.  The problem I'm having with this one is, when I try to pass a Dog to the real hook, nothing happens ... the client just times out and I don't get an exception or anything (not that I could catch).

So here's a description of the source for anyone who takes the time to check it out:

[[ "Remoting Rover" ]]

[[ Concept ]]
Vendor application (Veterinary app called 'VetApp' which is a database of animals) has OLE Hooks, including one called DogsHook (seen here) which is triggered when there's a DogInsert/DogEdit/DogDelete and, just for good measure, when there's a Bark.  We can't to consume these events with an assembly and pass all of the hook methods and the parameters passed on to another implementation via .NET Remoting.

All assemblies are pre-compiled in the bin directory of the project folder.  If you want to make changes and re-compile (if you don't have NAnt on your machine, you can download the source with NAnt and, no installation required, the builds should all work), make your changes and run 'rebuild.bat' in the src folder.

[[ Assemblies ]]
interop.vetapp.dll
-  RCW of an unmanaged assembly (that simply contains a Very simple 'Dog' class - this is our 'unmanaged' and wrapped object that we want to pass around)

VetApp.Hooks.dll
-  This assembly has all of the interfaces for VetApp hooks in it, in this case just IDogsHook.  These are used for compile-time errors if the implementing classes don't implement VetApp hooks correctly, and also as objects that can be passed around via Remoting.

RemotingRover.dll
    - Hook (represents a hook)
    - ProxyHook (represents a hook that connects to the ProxyClient to pass data along to the server)
    - ProxyServer (remotable object, stores references to Proxy hooks and 'Real' hooks)
    - ProxyServerManager (used to start and host a ProxyServer)

VetApp.ProxyHook.dll
-  This is the hook that we want VetApp to pass things to, and we want ProxyHook to, in turn, pass all of this data further along, across app boundaries to our Remoting server

RemotingRover.RealHook.dll
-  This is a 'real' implementation of our hook.  it's registered with the server and, when the server gets a request from a ProxyHook for it's real implementation, it gives a reference to the RealHook.  really, the server-hosting application loads a directory of these and the end user can select which one is active.

Client.exe
-  Console app being used to emulate VetApp.  run it after you start the server (below)

Server.exe
-  Console app being used to host the server and register our 1 real hook with it.

-------------------------------------------
**
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsent7/html/vxoriChoosingBusinessLogicTechnologies.asp

... that makes me think that I shouldn't have a problem with this.

"It is possible to call COM components directly through COM Interop Services. When the .NET Remoting client object creates an instance of a COM object, a runtime callable wrapper (RCW) exposes the unmanaged object and acts as a proxy for it. To the .NET client, this wrapper appears to be just like any other managed class. The wrapper simply marshals calls between managed (.NET) and unmanaged (COM) code."
ASKER CERTIFIED SOLUTION
Avatar of EE_AutoDeleter
EE_AutoDeleter

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial