实现IDispatch在c# [英] Implementing IDispatch in c#

查看:624
本文介绍了实现IDispatch在c#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 
 {
 ...
 }

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

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;

其中IDispatch定义为:

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

抛出InvalidCastException异常。是否可以将一个c#接口转换为IDispatch?

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

推荐答案

您需要使用regasm注册程序集,并且您需要使用[ ComVisible]属性。您可能还需要使用tlbexp(生成)和tregsvr来生成和注册类型库以进行注册。

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.

此外(从Win32角度来看)disp =(IDispatch)obj不同于dispispobject = IDispatch - 使用'as'

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.

最后,使用c#的'dynamic'类型来调用对象的QueryInterface方法来获取所请求的接口的指针,而不是尝试将对象强制转换到接口。可能会更接近其他家伙正在做的访问您的类。

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

这篇关于实现IDispatch在c#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆