如何手动将 .NET 对象编组为双 COM 接口?

Posted

技术标签:

【中文标题】如何手动将 .NET 对象编组为双 COM 接口?【英文标题】:How to manually marshal a .NET object as a dual COM interface? 【发布时间】:2017-06-12 19:22:53 【问题描述】:

我编写了一些 C# 代码,它使用 Marshal.GetIDispatchForObject 将 .NET 对象作为 IDispatch 指针返回给非托管代码,但是,该对象还实现了其他(非 .NET 定义的)COM 接口。 在非托管世界中,QueryInterface 这些接口工作正常,但是,在它们上调用方法永远不会破坏我的 .NET 代码,并且似乎只返回默认值 (0)。

是否可以将 .NET 对象编组为双接口,以便可以通过 IDispatch 或通过查询特定接口来使用它?我的类型是公开的,ComVisible,我尝试申请[ClassInterface(ClassInterfaceType.AutoDual)],但没有运气。

使用UnmanagedType.Interface marshaling 让事情正常工作没有任何问题,但是,支持IDispatch 似乎也有问题。如果有一种简单的方法来“手动”实现IDispatch,这也是一个可以接受的解决方案。

【问题讨论】:

很久没搞这些杂草了,不过我觉得你应该把类接口属性设置为None,自己手动实现IReflect接口。 【参考方案1】:

您可以使用ICustomQueryInterface interface。它将允许您“手动”返回 IUnknown 接口,并且仍然可以从 .NET 提供的 IDispatch 实现中受益。 因此,例如,如果您有一个包含一个方法(在示例中名为“MyUnknownMethod”)的非托管 IUnknown 接口“IMyUnknown”,您可以像这样声明您的 .NET 类:

[ComVisible(true)]
public class Class1 : ICustomQueryInterface, IMyUnknown

    CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv)
    
        if (iid == typeof(IMyUnknown).GUID)
        
            ppv = Marshal.GetComInterfaceForObject(this, typeof(IMyUnknown), CustomQueryInterfaceMode.Ignore);
            return CustomQueryInterfaceResult.Handled;
        

        ppv = IntPtr.Zero;
        return CustomQueryInterfaceResult.NotHandled;
    

    // an automatic IDispatch method
    public void MyDispatchMethod()
    
       ...
    

    // the IMyUnknown method
    // note you can declare that method with a private implementation
    public void MyUnknownMethod()
    
       ...
    

【讨论】:

以上是关于如何手动将 .NET 对象编组为双 COM 接口?的主要内容,如果未能解决你的问题,请参考以下文章

将 COM 接口编组到多个线程时,克隆流是不是足够,还是需要复制?

当类在另一个命名空间中时编组 .NET 对象

如何将 .NET 字符串正确编组为本机代码的 std::wstrings?

如何将 C++ 本机对象编组到托管 C++ CLI

如何将 JAXB 对象编组到 org.w3c.dom.Document?

在 JaxB 编组期间将字符串截断到最大限制