Разъяснение о том, как правильно объявлять интерфейсы взаимодействия
Вопрос
Это всего лишь вопрос о том, как написать мой код для импорта COM.
Мое понимание правильной реализации интерфейсов взаимодействия состоит в том, что основные критерии таковы:
<Ол>Мой вопрос Что мне делать в том порядке, в котором отображаются элементы, если импортируемый мной интерфейс наследуется от другого интерфейса и переопределяет / скрывает один или несколько элементов в базовом интерфейсе? Куда идет объявление члена интерфейса? Во-первых, где базовый интерфейс это объявил? Или удален из своей исходной позиции и помещен туда, где его объявляет производный интерфейс?
[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();
}
Решение
У вас есть пример того, как кто-то на самом деле это делает? Хотя в 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.
Другие советы
Я предлагаю вам использовать явные реализации членов интерфейса а> чтобы избежать конфликта.