简体   繁体   English

处理kludgy接口层次结构(MSHTML)的最佳方法是什么?

[英]What is the best way to deal with kludgy interface hierarchies (MSHTML)?

I'm using the MSHTML API from C# 4.0 and the logistics of running code are not a problem. 我正在使用C#4.0中的MSHTML API ,运行代码的后勤工作不是问题。 Writing the code, however, is a pain due to the way that MSHTML and/or COM interfaces are designed. 但是,由于设计MSHTML和/或COM接口的方式,编写代码很麻烦。 Specifically, there is no interface hierarchy when there should be one. 具体来说,应该有一个接口层次结构。 For example, IHTMLDocument7 does not extend IHTMLDocument6 , which doesn't extend IHTMLDocument5 , and so on ( IHTMLDocument2 does extend IHTMLDocument , though). 例如, IHTMLDocument7不会扩展IHTMLDocument6 ,它不会扩展IHTMLDocument5 ,依此类推(不过, IHTMLDocument2确实扩展了IHTMLDocument )。

To further confuse matters there is an HTMLDocument interface that extends DispHTMLDocument (which has all of the methods of the IHTMLDocument* interfaces) and HTMLDocumentEvents_Event (which provides some, but not all, events). 更令人困惑的是,有一个HTMLDocument接口扩展了DispHTMLDocument (具有DispHTMLDocument IHTMLDocument*接口的所有方法)和HTMLDocumentEvents_Event (提供了一些但不是全部事件)。 To add to the mess, HTMLDocumentClass is a coclass that implements all of the aforementioned interfaces and then some, such as IDocumentSelector and HTMLDocumentEvents4_Event . 更麻烦的是, HTMLDocumentClass是一个协类,它实现了所有上述接口,然后实现了某些接口,例如IDocumentSelectorHTMLDocumentEvents4_Event

I'd really like to be able to work with the API of HTMLDocumentClass , but trying to cast to it gave me: 我真的很希望能够使用HTMLDocumentClass的API,但是尝试将其强制转换为我:

System.InvalidCastException: Unable to cast COM object of type 'mshtml.HTMLDocumentClass' to class type 'mshtml.HTMLDocumentClass'. System.InvalidCastException:无法将类型为“ mshtml.HTMLDocumentClass”的COM对象转换为类类型为“ mshtml.HTMLDocumentClass”的对象。 Instances of types that represent COM components cannot be cast to different types that represent COM components; 表示COM组件的类型的实例不能转换为表示COM组件的不同类型; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface. 但是,只要基础COM组件支持对接口IID的QueryInterface调用,就可以将它们强制转换为接口。

In addition, some of the interfaces don't have an associated coclass; 另外,某些接口没有关联的协类。 eg, there are IHTMLElement* interfaces but no HTMLElement interface nor a HTMLElementClass class. 例如,有IHTMLElement*接口,但没有HTMLElement接口,也没有HTMLElementClass类。 Overall, I am finding it difficult to program to an interface. 总的来说,我发现很难对接口进行编程。

Are there good techniques for wrangling with this interface train wreck, or should I give up IntelliSense and use dynamic everywhere? 是否有解决此接口列车残障的好的技术,还是我应该放弃IntelliSense并在任何地方使用dynamic I considered writing wrapper classes that implemented all of the interfaces, but there are so many MSHTML interfaces and each of them has a ton of members so a practical solution has to be automated. 我考虑过编写实现所有接口的包装器类,但是有太多的MSHTML接口,每个接口都有大量的成员,因此实际的解决方案必须自动化。

IHTMLDocument6 doesn't extend IHTMLDocument5 IHTMLDocument6不扩展IHTMLDocument5

Even if it extends IHTMLDocument5, per COM rules, you are still supposed to QueryInterface to get IHTMLDocument5, not to use inheritance. 即使它扩展了IHTMLDocument5,按照COM规则,您仍然应该使用QueryInterface来获取IHTMLDocument5,而不使用继承。 I am glad that they did not let you wonder how you can QI for an interface that is already implemented by the wrapper class as a side effect of inheritance. 我很高兴他们没有让您想知道如何对包装类已经实现作为继承的副作用的接口进行QI。

I suggest you to not use any of the wrapper classes and switch to backward compatible interfaces when you control the objects. 我建议您在控制对象时不要使用任何包装器类,并切换到向后兼容的接口。 The COM wrapper CLR generated for IE looks like a mshtml.HTMLDocumentClass class from a different assembly, based on the error message. 根据错误消息,为IE生成的COM包装器CLR看起来像是来自不同程序集的mshtml.HTMLDocumentClass类。

In COM programming you would see the factory pattern quite often. 在COM编程中,您会经常看到工厂模式。 For the html element object, the factory method is IHTMLDocument2.createElement. 对于html元素对象,工厂方法为IHTMLDocument2.createElement。 Usually you can not create the object on your own if the author choose to use this pattern. 通常,如果作者选择使用此模式,则无法自行创建对象。

Visual Studio would automatically reference the PIA if one exists, otherwise it uses tlbexp.exe to generate interop assembly prefixed with "Interop". 如果存在,Visual Studio会自动引用PIA,否则它会使用tlbexp.exe生成以“ Interop”为前缀的互操作程序集。 However most of time you would be using a handful interfaces in the PIA, so you can write your own interop types (or copy from Google Code Search) and get ride of this big assembly. 但是,大多数情况下,您会在PIA中使用少量接口,因此您可以编写自己的互操作类型(或从Google Code Search复制)并使用这个大型程序集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM