Разъяснение о том, как правильно объявлять интерфейсы взаимодействия - PullRequest
1 голос
/ 24 октября 2009

Это всего лишь вопрос о том, как написать мой код для импорта COM.

Мое понимание правильной реализации интерфейсов взаимодействия состоит в том, что основные критерии таковы:

  1. Все сигнатуры методов должны соответствовать совместимым образом
  2. Методы должны отображаться в том же порядке в интерфейсе .Net, как и в неуправляемом интерфейсе.
  3. Когда неуправляемый интерфейс наследует от другого неуправляемого интерфейса, управляемая реализация должна сначала объявить членов интерфейса базового уровня, начиная с самого базового интерфейса.

Мой вопрос; Что мне делать в том порядке, в котором отображаются элементы, если импортируемый мной интерфейс наследуется от другого интерфейса и переопределяет / скрывает один или несколько элементов в базовом интерфейсе? Куда идет объявление члена интерфейса? Во-первых, где базовый интерфейс это объявил? Или удален из своей исходной позиции и помещен туда, где его объявляет производный интерфейс?

[uuid(31d1c294-1dd2-11b2-be3a-c79230dca297)]
interface BaseComInterface
{
    void method1();
    void method2();
    void method3();
}

[uuid(fab51c92-95c3-4468-b317-7de4d7588254)]
interface DerivedComInterface : BaseComInterface
{
    void method1();
    void method4();
    void method5();
}

Теперь для кода C #:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
    void method1(); // do I remove this one?
    void method2();
    void method3();
    void method1(); // or this one?
    void method4();
    void method5();
}

Ответы [ 2 ]

1 голос
/ 25 октября 2009

У вас есть пример того, как кто-то на самом деле это делает? Хотя в COM вполне законно иметь одно и то же имя для метода в интерфейсе и в другом производном от него интерфейсе, это делает работу с производным интерфейсом сложной или невозможной практически во всех средах разработки. Это включает в себя реализацию, а также вызов любых COM-объектов на основе интерфейса.

Нет такой вещи, как переопределение или скрытие в интерфейсе COM. Интерфейс COM - это просто контракт на то, как двоичный интерфейс объекта будет размещен в памяти, имена методов в определении интерфейса не имеют смысла, за исключением инструментов. В вашем случае BaseComInterface обещает «vtable» с шестью методами, первые три соответствуют сигнатурам методов IUnknown, а следующие три соответствуют сигнатурам трех методов, которые вы дали, все в правильном порядке. С другой стороны, DerivedComInterface обещает «vtable», который включает девять методов, опять же первые три сигнатуры соответствуют методам IUnknown, следующие три соответствуют сигнатурам методов BaseComInterface, а последние три соответствуют трем методам, уникальным для DerivedComInterface. Имена этих методов не имеют значения, за исключением вашей IDE, инструментов и компилятора, которым требуются имена для поиска указателей 'vtable'.

Таким образом, в основном в C #, а также в C, C ++ и некоторых других языках для реализации DerivedComInterface одно из имен методов должно быть декорировано, чтобы отличить его слот «vtable» от другого.

Чтобы ответить на ваш вопрос - вы не удалите ни один из методов, поскольку они оба должны быть там, чтобы выполнить контракт COM:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport,  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
    void method1(); 
    void method2();
    void method3();
    void method1_2(); //Decorated to distinguish from base interface method.
    void method4();
    void method5();
}

Это игнорирует то, что произойдет, если эти интерфейсы будут производиться от IDispatch, а не от IUnknown, - беспорядок, в который я бы не хотел попасть. Кроме того, помните, что если ваш idl действительно определяет методы как возвращающие void, вы должны декорировать ваши методы C # атрибутом PreserveSig.

0 голосов
/ 25 октября 2009

Я предлагаю вам использовать явные реализации членов интерфейса , чтобы избежать конфликта.

...