Объявления интерфейса COM

При создании объявлений 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);
}

То есть объявить его в одном интерфейсе, при этом принимая во внимание порядок членов.

Итак, каковы рекомендации по объявлению управляемых интерфейсов для их неуправляемых аналогов? Есть ли способ добиться того, чего я хочу, это наследование интерфейса на управляемой стороне + объявление членов в любом порядке, который я хочу (я действительно просто хочу отсортировать их по алфавиту)


person TheCodeJunkie    schedule 15.09.2009    source источник


Ответы (1)


Ваши открытия вызваны одним и тем же: vtables. Вы не можете изменить порядок vtable, и интерфейсы, которые наследуются от других интерфейсов, также всегда имеют все базовые записи в vtable. Итак, правила, которые вы ищете, это «убедитесь, что виртуальная таблица такая же».

person i_am_jorf    schedule 15.09.2009
comment
Значит, .net не балует меня автоматическим сопоставлением записей vtable на основе имен? В любом случае, чтобы настроить его с помощью атрибутов и т. д.? И почему не работает наследование? Неуклюже это объединит виртуальные таблицы по цепочке наследования? То есть сначала записи для ITaskbarList, затем для ITaskbarList2, а затем для ITaskbarList3.. или я получаю только записи из последнего интерфейса в ITaskbarList3, несмотря на наследование? - person TheCodeJunkie; 16.09.2009
comment
‹quote›интерфейсы, которые наследуются от других интерфейсов, также всегда имеют все базовые записи в vtable‹/quote› Разве это не означает, что если порядок элементов в каждом интерфейсе правильный, то записи vtable для интерфейса , который наследует другой интерфейс, окажется правильным? - person TheCodeJunkie; 16.09.2009
comment
Я отвечу на свой собственный дополнительный вопрос. Взаимодействие .NET не поддерживает наследование интерфейса, поэтому вам необходимо переопределить элементы родительского интерфейса в дочерних интерфейсах. - person TheCodeJunkie; 16.09.2009