2017-04-20 143 views
2

我一直在開發Web服務在C#鏈接網站與本地數據庫。本地應用程序的SDK是一個COM對象。我打破我的心就如何轉換下面的VB代碼的第二日(在SDK協議給予),以C#相當於:如何投射IDispatch在C#

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

我已經試過這樣:

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(); 

[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 
      ); 
     } 

,但我得到的錯誤

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. 

請幫我解決一下如何在C#中投射IDispatch。

+1

很明顯,您正在使用.NET XmlDocument類,而不是它的非託管味道(MSXML2.DOMDocument.3.0)。它不能轉換爲IDispatch。項目>添加參考> COM選項卡,選擇「Microsoft XML,v3.0」 –

+0

@HansPassant添加對「Microsoft XML,v3.0」的引用。什麼應該是傳遞參數部分:GetData(XML_DOM作爲Idispatch)? –

+1

使用'new MSXML2.DOMDocument30()'創建對象,不需要強制轉換。 –

回答

1

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.

你的問題是在這裏:

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

XmlDocument不是一個標準的OLE自動化/調度方式。這不是一個:

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

...或物體暴露IDispatchXmlDocument未實現的COM接口。 XmlDocument需要[ComVisible]出席。

如果對象是COM兼容的,那麼你可以只:

comObject.SomethingOrOther(myComCompliantObject); 

...沒有不必要的演員。

+0

解決方法是什麼?我應該使用哪個對象來實現IDispatch? –

+0

我能想到的唯一解決方法是如果你有權訪問COM庫的源代碼,並且能夠使它成爲C++/CLI,那麼你可以將任何舊的'object'傳遞給COM方法,然後一旦進入你可以將'IUnknown'強制轉換爲一個已知類型的被管理對象。我必須用遺留代碼做一次。我將在明天發佈代碼片段 – MickyD

+0

不幸的是,我無法訪問COM的源代碼。可以用以下方法調用所需的COM方法:comObject.GetType()。InvokeMember(「GetData」.....如果是,那麼如何? –