Как объявить и реализовать COM-интерфейс на C#, который наследовался другому COM-интерфейсу?

Я пытаюсь понять то, что является корректным, почему реализовать COM-интерфейсы из кода C#. Это просто, когда интерфейс не наследовался другому основному интерфейсу. Как этот:

[ComImport, Guid("2047E320-F2A9-11CE-AE65-08002B2E1262"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellFolderViewCB
{
  long MessageSFVCB(uint uMsg, int wParam, int lParam);
}

Однако вещи начинают становиться weired, когда я должен реализовать интерфейс, который наследовался другим COM-интерфейсам. Например, если я реализую IPersistFolder2 интерфейс, который наследовался IPersistFolder который наследовался IPersist как я обычно на коде C#:

[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);
}

Операционная система не может назвать методы на моей реализации объектов. То, когда я отлаживаю I, видит конструктора моего 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) { ... }
}

То, что кажется странным, - когда я объявляю импорт 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);
}

Я не знаю, почему это работает, когда я объявляю COM-интерфейсы тот путь (hidding основное использование методов интерфейса new). Возможно, это связано со способом, которым работает IUnknown. Кто-либо знает то, что корректный способ реализовать COM-интерфейсы в C#, который наследовался другим COM-интерфейсам и почему?

5
задан CARLOS LOTH 1 June 2010 в 20:07
поделиться

1 ответ

Отличный трюк с ключевым словом new, это действительно решит проблему. Проблема здесь в том, что COM не поддерживает наследование. В IDL это просто удобная нотация, чтобы создать видимость наследования. В действительности, интерфейсная v-таблица должна объединять все "унаследованные" базовые интерфейсы. Другими словами, для интерфейса IPersistFolder он должен копировать слоты v-таблицы для 3 методов IUnknown и метода IPersist::GetClassID. CLR заботится о IUnknown btw.

v-таблица, которую создает .NET, не совместима с этой схемой, она не дублирует слоты методов базового класса.

3
ответ дан 15 December 2019 в 06:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: