我正在使用C#4.0中的MSHTML API,运行代码的后勤工作不是问题。然而,编写代码是一种痛苦,因为MSHTML和/或COM接口的设计方式。具体来说,应该有一个接口层次结构。例如,IHTMLDocument7
不会扩展IHTMLDocument6
,但不会扩展IHTMLDocument5
,依此类推(IHTMLDocument2
会延伸IHTMLDocument
。) p>
为了进一步混淆问题,有HTMLDocument
接口扩展DispHTMLDocument
(具有IHTMLDocument*
接口的所有方法)和HTMLDocumentEvents_Event
(提供一些,但不是所有的事件)。为了增加混乱,HTMLDocumentClass
是一个coclass,它实现了所有上述接口,然后是一些,例如IDocumentSelector
和HTMLDocumentEvents4_Event
。
我真的希望能够使用HTMLDocumentClass
的API,但是试图投射它给了我:
System.InvalidCastException:无法执行 转换类型的COM对象 'mshtml.HTMLDocumentClass'来上课 输入'mshtml.HTMLDocumentClass'。 表示COM的类型的实例 组件不能转换为不同的组件 表示COM组件的类型; 但是它们可以转换为接口 只要底层的COM component支持QueryInterface 要求接口的IID。
此外,一些接口没有关联的coclass;例如,有IHTMLElement*
个接口,但没有HTMLElement
接口,也没有HTMLElementClass
类。总的来说,我发现很难编程到界面。
是否有很好的技术可以解决这个界面列车残骸,或者我应该放弃IntelliSense并在任何地方使用dynamic
?我考虑编写实现所有接口的包装类,但是有很多MSHTML接口,每个接口都有很多成员,所以实用的解决方案必须自动化。
答案 0 :(得分:1)
IHTMLDocument6不会扩展IHTMLDocument5
即使它扩展了IHTMLDocument5,根据COM规则,你仍然应该使用QueryInterface来获取IHTMLDocument5,而不是使用继承。我很高兴他们不会让你想知道你如何能够通过包装类实现的接口作为继承的副作用。
我建议您在控制对象时不要使用任何包装类并切换到向后兼容的接口。根据错误消息,为IE生成的COM包装器CLR看起来像来自不同程序集的mshtml.HTMLDocumentClass类。
在COM编程中,您会经常看到工厂模式。对于html元素对象,工厂方法是IHTMLDocument2.createElement。如果作者选择使用此模式,通常您无法自己创建对象。
如果存在PIA,Visual Studio将自动引用PIA,否则它使用tlbexp.exe生成以“Interop”为前缀的互操作程序集。但是大部分时间你都会在PIA中使用少数接口,因此你可以编写自己的互操作类型(或从谷歌代码搜索中复制)并获得这个大装配。