lundi 26 novembre 2018

Use a COM object Interface by Reflection

I'm having some problems using a COM Object dynamically without adding the Assembly as a reference in my project.

The thing is that I will use my application in some computers that not necessarily has installaed those assemblies, and they need to be loaded from the server because they are COM+ Applications. So, to do this, I'm using the following code:

  Type _ObjectType;
        Type ObjectType
        {
            get
            {

                _ObjectType= Type.GetTypeFromProgID(APP_NAME, server);
                if (_ObjectType!= null)
                    return _ObjectType;


                _ObjectType= Type.GetTypeFromCLSID(new Guid(CLSID), server);
                if (_ObjectType!= null)
                    return _ObjectType;


                throw new Exception("Error al obtener instancia de " + APP_NAME + " en " + server);
            }
        }


         object _InstanceObject;
         object InstanceObject
        {
            get
            {


                if (ObjectType!= null)
                {
                    _InstanceObject= Activator.CreateInstance(ObjectType);
                }


                if (_InstanceObject!= null)
                    return _InstanceObject;
                else
                    throw new Exception("Error al obtener instancia de Object");
            }
        }

At this point I have an instance of that COM+ Aplication without adding those assemblies as a Reference to my project and I can call and consume methods of those instances using reflection as follows:

//The method I'm calling have two arguments, one ByVal and one ByRef
 object[] args = new object[]
                     {
                         arg1,
                        arg2
                     };

ParameterModifier modifier = new ParameterModifier(2);

                modifier[0] = false;
                modifier[1] = false;


ParameterModifier[] mods = { modifier };

dynamic Result = (dynamic)ObjectType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, null, InstanceObject, args, mods, null, null);

Up here, all right all perfect, in fact, I can use myy application from any computer with access to the server and get the results of the method.

BUT, here comes the problem.

The COM+ Application has an Interface, and that interface has some methods that I need to call, but using the previous approach I can not do it, I'm having the following error:

  • $exception {"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"} System.Runtime.InteropServices.COMException

So, I'm thinking, maybe that interface is not public or somethign like that, and I can't access that way, so, I try by adding the asembly as a reference and create a traditiona instance of the COM object interface:

        MySpaceName.IMyInterface ComInterfaceInstance = new MySpaceName.IMyInterface();
        ComInterfaceInstance.MyMethod(arg1, ref arg2);

But C# tells me that there is an error:

Can not create an instance of the class or abstract interface 'IMyInterface'

So I try to create an instance of the main COM+ object and then cast this object as the Interface that has the method I need, like this:

 MySpaceName.MyObject a = new  MySpaceName.MyObject();

string param1 = "Param1";
object parm2 = new object();

((MySpaceName.IMyInterface)a).MyInterfaceMehthod(param1, ref parm2 );

This works fine, the cast works ok and the method gives me the results in the param2 variable. But again, It is not viable for my project because I'cant add as a reference those assemblies.

I need to clear out that those COM+ applications are Delphi DLLs, and not .NET assemblies.

So....is there any way to cast the instance created as the needed interface using the interface name as string? O a way to call the interface method with reflection?

Something like:

dynamic Result = (dynamic)ObjectType.InvokeMember("IMyInterface.MyMethod", BindingFlags.InvokeMethod, null, InstanceObject, args, mods, null, null);

or somethig that allows me to call the interface method?

Can anyone help me?

Ok, thanks for reading,





Aucun commentaire:

Enregistrer un commentaire