COM接口声明

时间:2009-09-15 20:28:03

标签: c# com interop marshalling

在C#中创建COM接口声明时,您必须坚持使用“规则”吗?我认为有,并希望得到一些信息。例如,我正在玩ITaskbarList,ITaskbarList2和ITaskbarList3接口,在我看来,我

  • 必须完全按照它们在非托管接口声明中出现的顺序声明管理实现中成员的顺序。

例如,以下似乎可以正常工作

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
}

重新排序成员时会破坏功能

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void DeleteTab([In] IntPtr hwnd);
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
}
  • 必须在单个托管接口声明中声明继承的非托管接口,而不是在托管接口上使用继承。我想在他们自己的托管接口中声明每个非托管接口(使用Guid属性等)并在其间使用继承,而不是在每个新接口中重新声明父声明。

例如,这似乎不起作用

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
}

[ComImport]
[Guid("602D4995-B13A-429B-A66E-1935E44F4317")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList2
    : ITaskbarList
{
    void MarkFullscreenWindow(
        [In] IntPtr hwnd,
        [In, MarshalAs(UnmanagedType.Bool)] bool fullscreen);
}

相反,我被迫做以下

[ComImport]
[Guid("602D4995-B13A-429B-A66E-1935E44F4317")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList2
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
    void MarkFullscreenWindow(
        [In] IntPtr hwnd,
        [In, MarshalAs(UnmanagedType.Bool)] bool fullscreen);
}

即在仍然考虑成员顺序的同时在单个界面中声明它。

那么为非托管对手声明托管接口的准则是什么?无论如何要实现我想要的,它在托管端的接口继承+以我想要的任何顺序声明成员(我真的只想按字母顺序对它们进行排序)

1 个答案:

答案 0 :(得分:3)

你的发现是由同样的事情引起的:vtables。您无法更改vtable顺序,并且从其他接口继承的接口也始终具有vtable中的所有基本条目。因此,您正在寻找的规则是“确保vtable是相同的。”