在c#中实现IDispatch

pro*_*ach 6 c# com idispatch

我正在编写一些测试代码来模拟非托管代码,调用后期绑定COM对象的c#实现.我有一个声明为IDispatch类型的接口,如下所示.

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

 [ClassInterface(ClassInterfaceType.AutoDual)]
 public class TestImpl : TestInterface 
 {
 ...
 }
Run Code Online (Sandbox Code Playgroud)

当我使用下面的代码调用IDispatch的GetIDsOfNames函数时

  ..
  //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;
Run Code Online (Sandbox Code Playgroud)

IDispatch定义为:

 //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);
  }
Run Code Online (Sandbox Code Playgroud)

抛出InvalidCastException.是否可以将ac#接口转换为IDispatch?

Fra*_*lis 1

您需要使用 regasm 注册程序集,并且需要使用 [ComVisible] 属性标记要从 COM 访问的类。您可能还需要使用 tlbexp(生成)和 tregsvr 来生成和注册类型库来注册它。

另外(从 Win32 的角度来看)“disp = (IDispatch) obj”与“disp = obj as IDispatch”不同 - 使用“as”运算符实际上调用对象上的 QueryInterface 方法来获取指向所请求接口的指针,而不是尝试将对象强制转换为接口。

最后,使用 c# 的“动态”类型可能会更接近其他人访问您的类所做的事情。