Implementing IDispatch in c#

守給你的承諾、 提交于 2019-12-06 00:22:47

问题


I'm writing some test code to emulate unmanaged code calling my c# implementation of a late binding COM object. I have an interface that is declared as an IDispatch type as below.

 [Guid("2D570F11-4BD8-40e7-BF14-38772063AAF0")]
 [InterfaceType(ComInterfaceType.InterfaceIsDual)]
 public interface TestInterface
 {
     int Test();
 }

 [ClassInterface(ClassInterfaceType.AutoDual)]
 public class TestImpl : TestInterface 
 {
 ...
 }

When I use the code below to call IDispatch's GetIDsOfNames function

  ..
  //code provided by Hans Passant
  Object so = Activator.CreateInstance(Type.GetTypeFromProgID("ProgID.Test"));
  string[] rgsNames = new string[1];
  int[] rgDispId = new int[1];
  rgsNames[0] = "Test";

  //the next line throws an exception
  IDispatch disp = (IDispatch)so;

Where IDispatch is defined as:

 //code provided by Hans Passant
 [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
 private interface IDispatch {
     int GetTypeInfoCount();
     [return: MarshalAs(UnmanagedType.Interface)]
     ITypeInfo GetTypeInfo([In, MarshalAs(UnmanagedType.U4)] int iTInfo, [In, MarshalAs(UnmanagedType.U4)] int lcid);
     void GetIDsOfNames([In] ref Guid riid, [In, MarshalAs(UnmanagedType.LPArray)] string[] rgszNames, [In, MarshalAs(UnmanagedType.U4)] int cNames, [In, MarshalAs(UnmanagedType.U4)] int lcid, [Out, MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
  }

An InvalidCastException is thrown. Is it possible to cast a c# interface into IDispatch?


回答1:


You need to register you assembly with regasm, and you need to mark the classes you want to access from COM with the [ComVisible] attribute. You may also need to generate and register a type-library using tlbexp (to generate) and tregsvr to register it.

Also (from a Win32 perspective) "disp = (IDispatch) obj" is not the same as "disp = obj as IDispatch" - using the 'as' operator actually calls the QueryInterface method on the object to get the pointer to the requested interface, instead of trying to cast an object to to the interface.

Lastly using c#'s 'dynamic' type will probably be closer to what the other guys are doing to access your class.




回答2:


You should just be able to use reflection on the COM type to get the list of methods.

Type comType = Type.GetTypeFromProgID("ProgID.Test");
MethodInfo[] methods = comType.GetMethods();


来源:https://stackoverflow.com/questions/8069425/implementing-idispatch-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!