Свойства C # и TLBEXP (Com) [дубликат]

Это должно сработать для вас -

DECLARE @STOP_TIME DATETIME = '2016-05-10 03:31:00.000',@Start_Time DATETIME = '2016-05-10 02:25:34.000'
SELECT RIGHT('0' + CAST(DATEDIFF(S, @Start_Time, @STOP_TIME)        / 3600 AS VARCHAR(2)), 2) + ':'
    + RIGHT('0' + CAST(DATEDIFF(S, @Start_Time, @STOP_TIME) % 3600 /   60 AS VARCHAR(2)), 2) + ':'
    + RIGHT('0' + CAST(DATEDIFF(S, @Start_Time, @STOP_TIME) %   60        AS VARCHAR(2)), 2)
12
задан jonathanpeppers 7 December 2009 в 23:10
поделиться

4 ответа

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

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

11
ответ дан Hans Passant 21 August 2018 в 18:19
поделиться
  • 1
    Я изначально установил [PreserveSig] для удобства использования с моим тестированием в VBScript (который хочет испортить параметры), но он работает одинаково без (и имеет правильное определение IDL). Я собираюсь реплицировать методы в базовом классе, чтобы клиент не мог вызвать QueryInterface. – jonathanpeppers 8 December 2009 в 14:59
  • 2
    IMHO, этот является проблемой .net, COM полностью поддерживает интерфейс (не класс) наследования, и regasm мог бы сгенерировать TLB, у которого было выведено IClass из ComVisible IBaseClass. Я отмечаю, что когда это происходит, реализация класса IDispatch класса не знает о методах IBaseClass - очень разочаровывает. Ваш совет (QI) хорош в том случае, когда один компонент реализует несколько интерфейсов; согласно MVP в ссылке Джонатана, этот метод не будет работать с иерархией наследования , потому что он просто не поддерживается. – bacar 22 September 2010 в 21:54
  • 3
    @bacar: агрегация, возможно, является лучшим термином. Anyhoo, для реализации интерфейсов требуется конкретный класс. И чтобы работать с унаследованными COM-интерфейсами, компилятор должен сгенерировать несколько v-таблиц, по одному для каждого интерфейса. Это поддерживается только средами времени выполнения, которые поддерживают множественное наследование. .NET не является одним из них, довольно фундаментальным ограничением. Да, вы могли бы назвать эту проблему .NET, она никуда не приведет. – Hans Passant 22 September 2010 в 22:08
  • 4
    @Hans: конечно, требуется только 1 (глубокий) vtable, соответствующий самому производному интерфейсу? Множественные vtables должны быть необходимы только тогда, когда существует множественное наследование, а не то, что происходит после OP. (и даже тогда, .net поддерживает наследование / агрегацию из нескольких интерфейсов). – bacar 22 September 2010 в 22:25
  • 5
    @bacar - глубокий v-стол хлопотно. Он должен выполнять несколько несовместимых обязанностей, поддерживать указатели интерфейса интерфейса, а также виртуальные методы самого класса. Вы не можете контролировать размещение указателей. И класс .NET всегда имеет виртуальные методы, он наследует System.Object. Я не согласен с тем, что CLR могла бы лучше справиться с синтезом набора отдельных v-таблиц, особенно для COM-клиентов. Но этого не произошло, они нацелились на автоматизацию. Взлом интерфейсов IUnknown возможен, просто не очень. Ничего страшного в том, что у меня нет библиотеки типов. – Hans Passant 22 September 2010 в 22:43

Вот другой подход, который минимизирует работу и оставляет интерфейс чистым. Просто укажите дополнительное свойство, которое возвращает 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
0
ответ дан Basti 21 August 2018 в 18:19
поделиться

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

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

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

6
ответ дан Community 21 August 2018 в 18:19
поделиться
  • 1
    Оказывается, что это будет какая-то раздражающая дополнительная работа, чтобы сделать нашу сборку видимой. – jonathanpeppers 7 December 2009 в 23:43

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

0
ответ дан user2505497 21 August 2018 в 18:19
поделиться
Другие вопросы по тегам:

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