在c#中实现IDispatch
本文关键字:IDispatch 实现 | 更新日期: 2023-09-27 18:13:53
我正在编写一些测试代码来模拟调用延迟绑定COM对象的c#实现的非托管代码。我有一个被声明为IDispatch类型的接口,如下所示。
[Guid("2D570F11-4BD8-40e7-BF14-38772063AAF0")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface TestInterface
{
int Test();
}
[ClassInterface(ClassInterfaceType.AutoDual)]
public class TestImpl : TestInterface
{
...
}
当我使用下面的代码调用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;
其中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);
}
抛出InvalidCastException异常。是否有可能将c#接口转换为IDispatch?
你需要用regasm注册你的程序集,并且你需要用[ComVisible]属性标记你想从COM访问的类。您可能还需要使用tlbexp(用于生成)和tregsvr来生成和注册类型库。
Also(从Win32的角度)"disp = (IDispatch) obj"与"disp = obj as IDispatch"不同——使用"as"操作符实际上调用对象上的QueryInterface方法来获取指向所请求接口的指针,而不是试图将对象强制转换为接口。
最后,使用c#的"动态"类型可能会更接近其他人访问你的类的方式。
您应该能够在COM类型上使用反射来获取方法列表。
Type comType = Type.GetTypeFromProgID("ProgID.Test");
MethodInfo[] methods = comType.GetMethods();