C# “我怎么能?”;替换“;从COM返回到托管代码的对象的接口?
我面临并怀疑它们可能是由于将C# “我怎么能?”;替换“;从COM返回到托管代码的对象的接口?,c#,.net,com,rcw,C#,.net,Com,Rcw,我面临并怀疑它们可能是由于将dynamic指定为COM接口方法的返回类型而产生的。具体来说,这就是IHTMLDOMChildrenCollection接口在互操作中的结束方式: [DefaultMember("item")] [Guid("3050F5AB-98B5-11CF-BB82-00AA00BDCE0B")] [TypeLibType(4160)] public interface IHTMLDOMChildrenCollection : IEnu
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 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
}
dynamic
肯定会影响性能,因为它会在C#端创建大量包装。请尝试以下操作:[PreserveSig]int-Item(int-index[marshallas(UnmanagedType.IDispatch)]out-object-ppItem代码>[PreserveSig]
由于某些原因不起作用。然而,我确实“替换”了接口——它必须用[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
声明。我认为接口已经完全生成(TypeLibType、TypeLibFunc、DefautlMember很少使用),所以我没有仔细查看它的定义。它应该是InterfaceIsividual,而不是纯分派,否则您将再次遇到性能问题(.NET将始终使用Invoke,而不是直接调用方法)。[PreserveSig]应该可以工作。使用InterfaceSidual会导致AccessViolationException,因为它没有属性。在这种情况下,.NET会直接调用这些方法(这是perf所需的),因此这意味着定义不正确。实际上,接口二进制布局是先get_length
,然后get_newEnum
和item
,如下所示:
[DefaultMember("item")]
[Guid("3050F5AB-98B5-11CF-BB82-00AA00BDCE0B")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(4160)]
public interface IHTMLDOMChildrenCollectionCopy : IEnumerable
{
// same members as in the question
}