C # подвергание COM - наследованию интерфейса - PullRequest
12 голосов
/ 08 декабря 2009

Скажем, у меня есть класс BaseClass, который реализует IBaseClass

Тогда у меня есть интерфейс IClass, который наследует IBaseClass.

Тогда у меня есть класс с именем class, который реализует IClass.

Например:

[ComVisible(true), InterfaceType(ComInterfaceType.IsDual), Guid("XXXXXXX")]
public interface IBaseClass
{
  [PreserveSig]
  string GetA()
}

[ComVisible(true), InterfaceType(ComInterfaceType.IsDual), Guid("XXXXXXX")]  
public interface IClass : IBaseClass
{
  [PreserveSig]
  string GetB()
}

[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("XXXXXXX")]
public class BaseClass : IBaseClass
{
  public string GetA() { return "A"; }
}

[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("XXXXXXX")]
public class Class : BaseClass, IClass
{
  public string GetB() { return "B"; }
}

При использовании COM, если я создаю экземпляр класса, это не позволяет мне вызывать GetA ().

При просмотре моего IDL в файле .tlb мой интерфейс IClass выглядит следующим образом:

[
  odl,
  uuid(XXXXXXXXXXXXXXXXXXXXX),
  version(1.0),
  dual,
  oleautomation,

]
interface IClass : IDispatch {
    [id(0x60020000)]
    BSTR GetB();
}

Это даже не похоже на то, что IClass является производным от IBaseClass!

Если я возьму, откуда IClass наследуется от IBaseClass, и просто добавлю методы в интерфейс, он будет работать.

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

CRAP: проверьте эту ссылку .Net COM ограничение

Если у кого-то есть ответ на вопрос, почему это так, или лучший обходной путь, чем копирование-вставка в мой «производный» интерфейс, дайте мне знать. Если нет, я отмечу ответ через пару дней.

Ответы [ 4 ]

12 голосов
/ 08 декабря 2009

Это не проблема .NET, а следствие того, как работает COM. Это не поддерживает наследование. Вы должны исправить это на стороне клиента, он должен вызвать QueryInterface () с IID для IBaseClass, чтобы получить указатель интерфейса на интерфейс IBaseClass, чтобы он мог вызывать GetA (). Взаимодействие .NET автоматически обеспечивает реализацию QI, которая делает эту работу. Однако в этом случае это не очень удобно для пользователя, разработайте свой код на стороне C #, чтобы клиент мог легко использовать ваш класс, а не наоборот. Обычно вам понадобится метод переопределения, состоящий из одной строки, который делегирует реализацию базового класса C #.

Обратите внимание, что есть проблема с вашими сигнатурами методов и использованием атрибута [PreserveSig]. Они не могут быть вызваны через IDispatch и не могут быть автоматически маршалированы. Для этого требуется метод с HRESULT в качестве типа возвращаемого значения. Это происходит автоматически при удалении атрибута.

6 голосов
/ 08 декабря 2009

Похоже, что это очень похоже на этот вопрос: Наследование интерфейса в классах ComVisible в C #

Как вы отметили в своем редактировании, это ограничение на переход от .net к COM, так как интерфейс COM не включает никаких унаследованных интерфейсов.

В некоторых языках вы могли бы решить эту проблему, внедрив блок кода во все соответствующие интерфейсы, но, насколько я вижу, это невозможно в C #.

0 голосов
/ 20 июня 2013

используйте [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] в качестве атрибута для интерфейса, который расширяет другие. это обходной путь.

0 голосов
/ 26 марта 2013

Вот другой подход, который минимизирует работу и оставляет интерфейс чистым.
Просто укажите дополнительное свойство, которое возвращает BaseInterface:

public IBaseClass BaseProperties {
    get { return this; }
}

Конечно, вы должны добавить эту часть в свой интерфейс IBaseClass:

public ISingleShot BaseProperties { get; }



Вот соответствующий код VB.Net:

ReadOnly Property BaseProperties As ISingleShot
Public ReadOnly Property BaseProperties As IBaseClass Implements IClass.BaseProperties
  Get
    Return Me
  End Get
End Property
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...