了解COM / WSH行为 - 后期绑定IDispatch _Default和Item?

时间:2012-06-18 16:29:33

标签: c# com activex idispatch createinstance

我试图复制我在C#中用JScript观察到的行为。我正在使用IDispatch枚举成员并在后期绑定的对象上调用它们。我是一个完整的C ++ noob,并且知道COM非常危险。 以下是我的问题:

  • DISPID_VALUE始终为零(0)? (似乎是)
  • 调用COM对象时,何时应该调用DISPID_VALUE成员? (类似于,当界面本身被索引或调用时......?)
  • 是否有任何关于何时致电.Item?
  • 的规则/提示
  • 为什么在下面的例子中,BindingFlags.SetProperty对.Cells(x,x)(与BindingFlags.InvokeMethod相反)有效?它是否调用_Default(x,x)?项目(x,x)?怎么知道这样做?我怎样才能知道它在调用它?
  • 是否有一些关于调用后期绑定的IDispatch COM对象的好文档?

在下面的示例中,Excel电子表格的单元格1,1的值设置为某些文本和#34;粗体"。

考虑以下WSH JScript:


var objExcel = new ActiveXObject("Excel.Application");
objExcel.Workbooks.Add();
objExcel.Visible = true;
objExcel.Cells(1,1).Value = "some test value";
objExcel.Cells(1,1).Font.Bold = true;

这个C#代码创建了相同的结果(是的,抱歉,它非常详细):


Type axType = Type.GetTypeFromProgID("Excel.Application");
object objExcel = Activator.CreateInstance(axType);
object workbooks = objExcel.GetType().InvokeMember("Workbooks", System.Reflection.BindingFlags.GetProperty, null, objExcel, null);
objExcel.GetType().InvokeMember("Visible", System.Reflection.BindingFlags.SetProperty, null, objExcel, new object[] { true });
workbooks.GetType().InvokeMember("Add", System.Reflection.BindingFlags.InvokeMethod, null, workbooks, new object[] { true });
object cell = objExcel.GetType().InvokeMember("Cells", System.Reflection.BindingFlags.GetProperty, null, objExcel, new object[] { 1, 1 });
cell.GetType().InvokeMember("Value", System.Reflection.BindingFlags.SetProperty, null, cell, new object[] { "some test value" });
object font = cell.GetType().InvokeMember("Font", System.Reflection.BindingFlags.GetProperty, null, cell, null);
font.GetType().InvokeMember("Bold", System.Reflection.BindingFlags.SetProperty, null, font, new object[] { true });

当我有时间以某种方式获得时间时,我打算尝试进一步了解这是让JScript调用我将使用日志/调试创建的C#COM类。

1 个答案:

答案 0 :(得分:4)

是的,在oaidl.idl中,DISPID_VALUE #defined为0。赋予属性0的调度使其成为默认属性。许多语言允许省略默认属性的名称。相当于C#索引器。

这只是一个约定,当然不需要COM IDispatch派生接口来公开默认属性。该财产也不必被命名为“价值”。这样做很常见。 [ComVisible] C#接口的索引器将获得dispid 0,但名称为“Item”。周围有很多其他的变化,你不能假设任何东西。

BindingFlags.SetProperty可以工作,因为Cells成员是属性,而不是方法。它看起来有点像方法,因为它是索引属性。这在C#中几乎不受支持(仅适用于索引器),但在COM或VB.NET中不受限制。 COM IDispatch接口用于示例代码,它允许按名称查找成员。 IDispatch :: GetIDsOfNames()完成这项工作,将字符串映射到数字(dispid),然后可以使用IDispatch :: Invoke()来调用属性或方法。请注意,这仅适用于一种方式,名称为数字。 IDispatch不支持Reflection的等价物。

通过在VB.NET中编写或使用C#version 4 dynamic 关键字来摆脱丑陋的C#代码。