如何手动将 .NET 对象编组为双 COM 接口?
How to manually marshal a .NET object as a dual COM interface?
我已经编写了一些 C# 代码,其中 return 将 .NET 对象作为非托管代码的 IDispatch
指针使用 Marshal.GetIDispatchForObject
,但是,该对象还实现了其他(非 .NET定义)COM 接口。
在非托管世界中,这些接口的 QueryInterface
工作正常,但是,在它们上调用方法永远不会破坏我的 .NET 代码,并且似乎 return 仅默认值 (0)。
是否可以将 .NET 对象编组为双重接口,以便可以通过 IDispatch
或通过查询特定接口来使用它?我的类型是 public、ComVisible
,我尝试应用 [ClassInterface(ClassInterfaceType.AutoDual)]
,但没有成功。
使用 UnmanagedType.Interface
封送处理,我没有遇到任何问题,但是,支持 IDispatch
似乎也有问题。如果有 简单 的方法来 "manually" 实施 IDispatch
这也是一个可以接受的解决方案。
您可以使用ICustomQueryInterface interface。它将允许您 return IUnknown 接口 "manually" 并且仍然受益于 .NET 提供的 IDispatch 实现。
因此,例如,如果您有一个非托管 IUnknown 接口 "IMyUnknown",其中包含一个方法(在示例中名为 "MyUnknownMethod"),您可以像这样声明您的 .NET class:
[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()
{
...
}
}
我已经编写了一些 C# 代码,其中 return 将 .NET 对象作为非托管代码的 IDispatch
指针使用 Marshal.GetIDispatchForObject
,但是,该对象还实现了其他(非 .NET定义)COM 接口。
在非托管世界中,这些接口的 QueryInterface
工作正常,但是,在它们上调用方法永远不会破坏我的 .NET 代码,并且似乎 return 仅默认值 (0)。
是否可以将 .NET 对象编组为双重接口,以便可以通过 IDispatch
或通过查询特定接口来使用它?我的类型是 public、ComVisible
,我尝试应用 [ClassInterface(ClassInterfaceType.AutoDual)]
,但没有成功。
使用 UnmanagedType.Interface
封送处理,我没有遇到任何问题,但是,支持 IDispatch
似乎也有问题。如果有 简单 的方法来 "manually" 实施 IDispatch
这也是一个可以接受的解决方案。
您可以使用ICustomQueryInterface interface。它将允许您 return IUnknown 接口 "manually" 并且仍然受益于 .NET 提供的 IDispatch 实现。 因此,例如,如果您有一个非托管 IUnknown 接口 "IMyUnknown",其中包含一个方法(在示例中名为 "MyUnknownMethod"),您可以像这样声明您的 .NET class:
[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()
{
...
}
}