繁体   English   中英

如何“替换”从 COM 返回的对象的接口到托管代码?

[英]How can I "replace" the interface for an object returned from COM to managed code?

我面临一些奇怪的性能问题,我怀疑它们可能是由于将dynamic指定为 COM 接口方法的返回类型而引起的。 具体来说,这就是 IHTMLDOMChildrenCollection 接口在互操作中的结束方式:

[DefaultMember("item")]
[Guid("3050F5AB-98B5-11CF-BB82-00AA00BDCE0B")]
[TypeLibType(4160)]
public interface IHTMLDOMChildrenCollection : IEnumerable
{
    [DispId(-4)]
    [TypeLibFunc(65)]
    IEnumerator GetEnumerator();
    [DispId(0)]
    dynamic item(int index); // HERE is the dynamic

    [DispId(1500)]
    int length { get; }
}

我怀疑一旦我的代码调用item()方法,就会创建一些额外的接线,这会降低其他代码的性能。

代码组织如下:

var document = (IHTMLDocument)documentBrowser.Document;
var selector = (IDocumentSelector)document;
IHTMLDOMChildrenCollection allElements = selector.querySelectorAll("*");
int length = allElements.length;
for (int index = 0; index < length; index++)
{
    var item = allElements.item(index);
}

这个答案指出,如果 IHTMLDOMChildrenCollection 接口被声明为item()返回object ,而不是dynamic ,则性能可能会提高。

是否可以声明一个新接口并以某种方式说服 CLR 给我一个实现该接口的 RCW?

我尝试了以下方法:

[DefaultMember("item")]
[Guid("3050F5AB-98B5-11CF-BB82-00AA00BDCE0B")]
[TypeLibType(4160)]
public interface IHTMLDOMChildrenCollectionCopy : IEnumerable
{
    [DispId(-4)]
    [TypeLibFunc(65)]
    IEnumerator GetEnumerator();
    [DispId(0)]
    [return: MarshalAs(UnmanagedType.IDispatch)]
    object item(int index); // HERE it's object, not dynamic

    [DispId(1500)]
    int length { get; }
}

并在代码中:

IHTMLDOMChildrenCollection allElementsOriginal = selector.querySelectorAll("*");
var unknown = Marshal.GetIUnknownForObject(allElements);
var newElements = (IHTMLDOMChildrenCollectionCopy)Marshal.GetTypedObjectForIUnknown(
   unknown , typeof(IHTMLDOMChildrenCollectionCopy));
int length = newElements.length; // this fails

它一直工作到执行读取.length的行。 后者失败了

System.AccessViolationException: '试图读取或写入受保护的内存。 这通常表明其他内存已损坏。

这应该工作吗? 我究竟做错了什么?

是的,这应该有效。 缺失的部分是接口没有用[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

这是完整的声明:

[DefaultMember("item")]
[Guid("3050F5AB-98B5-11CF-BB82-00AA00BDCE0B")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(4160)]
public interface IHTMLDOMChildrenCollectionCopy : IEnumerable
{
   // same members as in the question
}

暂无
暂无

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

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