Попытка создать COM-компонент на C #, на который можно ссылаться и использовать из VB5 / 6

#c# #.net #com-interop

#c# #.net #com-взаимодействие

Вопрос:

Я пытаюсь посмотреть, смогу ли я создать COM-компонент на C # (.NET 4), который я могу использовать из программы VB5 (cue иронические замечания) для доступа к веб-службе. Следуя всем инструкциям, которые я смог найти в MSDN и CodeProject следующим образом:

Я написал следующее:

 [Guid("7A715F02-D349-45DC-B0AE-9925FD3B943C")]
public interface ARCOM_Interface
{
    [DispId(1)]
    string GetServiceResponse();
}

[Guid("5130F041-619E-41F9-84B6-8332642228F6")
    , InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ARCOM_Events
{
}

[Guid("0A77754F-34CF-4E0E-AAC2-85FD686758E0")
    , ClassInterface(ClassInterfaceType.None)
    , ComSourceInterfaces(typeof(ARCOM_Events))]
[ComVisible(true)]
public class ARCOM_Class : ARCOM_Interface
{
    public string GetServiceResponse()
    {
        string response = string.Empty;

        ARWebService.ARWebService svc = new ARWebService.ARWebService();

        response = svc.PingMeBack();

        return response;
    }
}
  

Рассматриваемая сборка подписана строгим именем, а выходные данные зарегистрированы для COM-взаимодействия. После сборки я применил к нему RegAsm и сгенерировал библиотеку типов с tlbexp.exe.

В VB6, когда я открываю список ссылок из свойств проекта, я могу найти сборку в списке, и я могу ее проверить. Я даже могу сделать следующее в коде VB6:

 Private Sub HitWebService()

    Dim arcom As ARCOMObject.ARCOM_Class

    arcom. <== Intellisense doesn't sense anything!

End Sub
  

Intellisense видит ARCOMObject и класс, но ничего, что находится внутри самого ARCOM_Class (за исключением обычных «GetType», «Equals» и других универсальных методов / свойств объекта). В частности, похоже, что он не видит метод GetServiceResponse(), поэтому я не могу его вызвать.

Что я упускаю?

Ответ №1:

Я вижу, вы разработали способ получить то, что вы хотите, пока я печатал этот ответ, но я все равно продолжу, потому что это может рассказать вам кое-что, чего вы не знаете…

Вы применили атрибут ClassInterface(ClassInterfaceType.None) к классу. Это указывает COM interop не определять явный интерфейс для класса, и поэтому ваш клиент должен использовать IDispatch (позднюю привязку). Это означает, что ваш клиент должен иметь априорные знания об интерфейсах, реализуемых классом. То есть вы (программист) знаете, какие методы доступны, но такие инструменты, как IntelliSense, не имеют возможности найти эту информацию.

Просто продолжайте и вызовите метод:

 Dim response As String
response = arcom.GetServiceResponse
  

Ответ №2:

Хорошо, я нашел кое-что, что неожиданно изменило ситуацию.

Обратите внимание, что приведенный выше код содержит оформление [ComVisible(true)]. Конечно, важно сделать сборку видимой для COM. Я думал, что это исчерпывающе, но при дальнейшем поиске я обнаружил, что есть другое место для его пометки. Если вы посмотрите в свойствах проекта, на вкладке Приложения вы найдете информацию о сборке… кнопка. Нажмите на него, и в нижней части диалогового окна вы увидите флажок «Сделать сборку COM-видимой». Я проверил его, перекомпилировал (и повторно запустил tlbexp и regasm), а затем обнаружил, что метод GetServiceResponse() был виден.

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

Отредактировано, чтобы добавить: Думаю, я понимаю, что с этим не так. Значение ComVisible (true) делает класс видимым для COM, но не для сборки; вот почему необходимо проверить «Сделать сборку COM-видимой», потому что метод GetServiceResponse, похоже, получает свою COM-видимость через ARCOM_Interface, который не помечен как ComVisible, если только сборка не является такой же.

Комментарии:

1. COM основан на интерфейсе. Важными элементами для создания [ComVisible] являются интерфейсы, а не класс. Вы сделали это с помощью флажка, он делает все видимым. VB6 нравится ComInterfaceType. Интерфейс является двойным, который помещает объявление интерфейса в библиотеку типов. Предоставляю вам автоматическое завершение процесса.