我试图理解从C#代码实现COM接口的正确原因是什么.当接口不从其他基接口继承时,它很简单.像这个:
[ComImport, Guid("2047E320-F2A9-11CE-AE65-08002B2E1262"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellFolderViewCB
{
long MessageSFVCB(uint uMsg, int wParam, int lParam);
}
Run Code Online (Sandbox Code Playgroud)
然而,当我需要实现从其他COM接口继承的接口时,事情开始变得疲惫不堪.例如,如果我实现IPersistFolder2继承的接口,就像我通常在C#代码上IPersistFolder继承的IPersist那样:
[ComImport, Guid("0000010c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersist
{
void GetClassID([Out] out Guid classID);
}
[ComImport, Guid("000214EA-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistFolder : IPersist
{
void Initialize([In] IntPtr pidl);
}
[ComImport, Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistFolder2 : IPersistFolder
{
void GetCurFolder([Out] out IntPtr ppidl);
}
Run Code Online (Sandbox Code Playgroud)
操作系统无法调用我的对象实现上的方法.当我调试时,我可以看到我的IPersistFolder2实现的构造函数被多次调用,但是我实现的接口方法没有被调用.我正在实施IPersistFolder2如下:
[Guid("A4603CDB-EC86-4E40-80FE-25D5F5FA467D")]
public class PersistFolder: IPersistFolder2
{
void IPersistFolder2.GetClassID(ref Guid classID) { ... }
void IPersistFolder2.Initialize(IntPtr pidl) { ... }
void IPersistFolder2.GetCurFolder(out IntPtr ppidl) { ... }
}
Run Code Online (Sandbox Code Playgroud)
看起来很奇怪的是当我声明COM接口导入如下时,它可以工作:
[ComImport, Guid("0000010c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IPersist
{
void GetClassID([Out] out Guid classID);
}
[ComImport, Guid("000214EA-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IPersistFolder : IPersist
{
new void GetClassID([Out] out Guid classID);
void Initialize([In] IntPtr pidl);
}
[ComImport, Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IPersistFolder2 : IPersistFolder
{
new void GetClassID([Out] out Guid classID);
new void Initialize([In] IntPtr pidl);
void GetCurFolder([Out] out IntPtr ppidl);
}
Run Code Online (Sandbox Code Playgroud)
当我以这种方式声明COM接口时(我隐藏基本接口方法new),我不知道它为什么会起作用.也许它与IUnknown的工作方式有关.有谁知道在C#中实现继承自其他COM接口的COM接口的正确方法是什么?为什么?
使用 new 关键字的巧妙技巧确实可以解决问题。这里的问题是 COM 不支持继承。IDL 中只是为了符号方便才使其看起来像这样。实际上,接口 v 表必须聚合所有“继承的”基本接口。换句话说,对于 IPersistFolder 接口,它必须复制 3 个 IUnknown 方法和 IPersist::GetClassID 方法的 v 表槽。顺便说一句,CLR 负责处理 IUnknown。
.NET 构建的 v-table 与此布局不兼容,它不复制基类方法槽。
| 归档时间: |
|
| 查看次数: |
9663 次 |
| 最近记录: |