I have a 3rd party component, lets say FIPreviewHandler to handle preview, which implements IPreviewHandler. FIPreviewHandler is implemented as a Managed Component, and uses the IPreviewHandler interface and related interfaces through means of an interop. FIPreviewHandler is registered using regasm.exe as COM.
I have a client application which is also Managed. I want to create an instance of FIPreviewHandler as a COM component in my application.
I have an interop assembly that defines IPreviewHandler and related interfaces.
When I create an instance of FIPreviewHandler, using Activator.CreateInstance(), on a type returned by GetTypeByCLSID(), which uses the correct CLSID for FIPreviewHandler, it returns me a managed instance, as it has the actual assembly available, and skips COM. When I try to QI/cast this instance as any of the interfaces, IPreviewHandler for example, it returns null because, it is loaded as a managed object, and although the IPreviewHandler interface implemented by FIPreviewHandler is the same interface as I have in my interop, but its in a difference namespace/assembly, hence null. If it were to return me a COM instance/RCW (System.__ComObject), it would not take namespace into account, and would cast fine, and return a valid instance.
FIPreviewHandler is a 32 bit component, and on a 64bit Win7 machine, if I compile my client application as "Any CPU", Activator.CreateInstance() returns a COM instance/RCW (System.__ComObject), as it cudnt find a 64bit implementation of FIPreviewHandler, hence returns a proxy. In this scenario, my application works fine. But when I compile it for x86, it gets the 32bit implementation, and returns a managed instance of the actual managed class, and not a COM instance, hence fails.
I cannot use the interfaces defined in FIPreviewHandler's assembly, as I have to write a generic client for IPreviewHandler, and my application will work with any component implementing IPreviewHandler, which would work great for C++ based clients accessing FIPreviewHandler as a COM object, but is failing for Managed clients.
I hope I make sense and I would be really grateful for any help.
So clearly this a fail on .NET's part as I'm finding there is no way to use a COM wrapper around a managed COM object.
The "solution" (and I use that term very loosely) is the use of a PIA or 'Primary Interop Assembly'. The PIA provides a single strong-named assembly imported with TlbImp.exe that is GAC registered. Basically I guess we then must rely on GAC publisher policies to force clients to the correct interface assembly.
see also
http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/b11a0f90-fcc5-487a-b057-632f5415bfc2
http://www.codeproject.com/KB/COM/BuildCOMServersInDotNet.aspx
Man, if I were you, I would just make the wrapper myself, only when the type is NOT a COM type. To know if the type created is a COM type, use the IsCOMObject
from the Type
of the object:
myObject.GetType().IsCOMObject
If this is FALSE create a wrapper, that uses reflection to call the managed type. Reflection is slow, but you can cache the MethodInfo
objects that you get... otherwise you can generate IL code, and create a wrapper that will have no reflection at all.
Of course there are other methods, of doing it... this is up to you.
As I am in love with dynamic run-time IL generation, I can provide you with a code that does this... if you are interested!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With