Search code examples
c#commsxml

How to cast IDispatch in C#


I've been developing a web-service in c# to link web-site with local db. SDK for local application is a COM object. The second day I am breaking my mind on how to convert the below VB code(given in SDK protocol) to C# equivalent:

XML_DOM := CreateOleObject('MSXML2.DOMDocument.3.0') as IXMLDOMDocumen
GetData(XML_DOM as Idispatch)

I've tried this:

System.Type objType = System.Type.GetTypeFromProgID("PERCo_S20_SDK.ExchangeMain");
            dynamic comObject = System.Activator.CreateInstance(objType);
            if (comObject.SetConnect("192.168.1.14", "211", "ADMIN", "") != 0)
            {
                    //Could not connect to server!
            }
            XmlDocument dep_xml = new XmlDocument();
            XmlDeclaration dep_xml_decl = dep_xml.CreateXmlDeclaration("1.0", "UTF-8", "yes");
            XmlElement root = dep_xml.DocumentElement;
            dep_xml.InsertBefore(dep_xml_decl, root);
            XmlElement element = dep_xml.CreateElement(string.Empty, "documentrequest", string.Empty);
            element.SetAttribute("type", "subdiv");
            dep_xml.AppendChild(element);
            comObject.GetData(dep_xml as IDispatch);
            comObject.Disconnect();

with

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
        private interface IDispatch
        {
            [PreserveSig]
            int GetTypeInfoCount(out int Count);

            [PreserveSig]
            int GetTypeInfo
            (
              [MarshalAs(UnmanagedType.U4)] int iTInfo,
              [MarshalAs(UnmanagedType.U4)] int lcid,
              out System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo
            );

            [PreserveSig]
            int GetIDsOfNames
            (
              ref Guid riid,
              [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
                string[] rgsNames,
              int cNames,
              int lcid,
              [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId
            );

            [PreserveSig]
            int Invoke
            (
              int dispIdMember,
              ref Guid riid,
              uint lcid,
              ushort wFlags,
              ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
              out object pVarResult,
              ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
              out UInt32 pArgErr
            );
        }

but I get error

An exception of type 'System.ArgumentException' occurred in System.Dynamic.dll but was not handled in user code

Additional information: Could not convert argument 0 for call to GetData.

Please help me out how should I cast IDispatch in C#.


Solution

  • An exception of type 'System.ArgumentException' occurred in System.Dynamic.dll but was not handled in user code

    Additional information: Could not convert argument 0 for call to GetData.

    Your problem is here:

     XmlDocument dep_xml = ...
     comObject.GetData(dep_xml as IDispatch);  // <------ BANG!!
    

    XmlDocument is not a standard OLE automation/dispatch type. It is not a:

    • int
    • float
    • char
    • BSTR
    • SAFEARRAY
    • etc

    ...or an object exposing IDispatch, a COM interface that XmlDocument does not implement. XmlDocument would require [ComVisible] to be present.

    If the object were COM-compliant, then you could just:

     comObject.SomethingOrOther(myComCompliantObject);
    

    ...without the unnecessary cast.