2017-04-20 20 views
2

저는 웹 사이트를 로컬 db와 연결하기 위해 C#으로 웹 서비스를 개발했습니다. 로컬 응용 프로그램 용 SDK는 COM 개체입니다. 나는 VB 코드 아래를 변환하는 방법에 대한 내 마음을 파괴하고 둘째 날은 C#을 동등한 (SDK 프로토콜에 주어진) :C#에서 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(); 

로 :

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

나는이 시도했다

[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 클래스를 사용하고 있으며 관리되지 않는 Flavor (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

... 또는 객체가 012 노출 : 그것은 아니다, XmlDocument이 구현하지 않는 COM 인터페이스 XmlDocument에는 [ComVisible]이 필요합니다. 객체가 COM을 준수한다면

, 당신은 단지 수 : 불필요한 캐스트없이

comObject.SomethingOrOther(myComCompliantObject); 

....

+0

해결 방법은 무엇입니까? IDispatch를 구현하기 위해 어떤 객체를 사용해야합니까? –

+0

내가 생각할 수있는 유일한 해결 방법은 COM 라이브러리의 소스에 액세스하여이를 C++/CLI로 만들 수 있다면 COM 객체에 이전의 객체를 전달할 수 있다는 것입니다. 'IUnknown'을 알려진 유형의 관리 객체에 캐스트 할 수 있습니다. 레거시 코드를 사용하여이 작업을 한 번 수행해야했습니다. 나는 내일 코드 조각을 게시 할 것이다. – MickyD

+0

불행히도 나는 COM의 소스에 접근 할 수 없다. comObject.GetType(). InvokeMember ("GetData"..... 그렇다면, 어떻게? –