Как отладчик / интерактивное окно Visual Studio выводит свойства COM-объектов в.NET?

В этом смежном вопросе я отметил, что отладчик Visual Studio может перечислять свойства System.__ComObject ссылки, которые являются "скрытым типом, используемым, когда тип оболочки является неоднозначным" - например, тип объекта, который вы получаете, когда получаете его от другого COM-объекта и не создаете его экземпляр самостоятельно:

Просмотр отладки COM-объектов

Кроме того, если вы просто запишите идентификатор COM-объекта в Immediate Window, его свойства и значения будут сброшены аналогичным образом:

COM-объект непосредственного окна

Обратите внимание, что это отдельно от " Dynamic View " VS2010, который я считаю, использует IDispatch и COM-отражение для перечисления свойств COM-объектов без использования PIA и.NET-отражения. Объекты, с которыми я работаю, не реализуются IDispatch (и при этом они не реализуют IProvideClassInfo В этом отношении "Dynamic View" не может получить никакой информации о них:

Динамический просмотр

Интересно, что отладчик SharpDevelop не может перечислить членов System.__Comobject s (например, point.Envelope), только строго типизированные RCW (например, point).

SharpDevelop отладчик

Итак, как Visual Studio может это сделать?

Я полагаю, что в этом случае это происходит потому, что существуют основные сборки взаимодействия с определениями интерфейсов, поддерживаемых этими объектами, и Visual Studio, вероятно, использует отражение для перечисления поддерживаемых интерфейсов и свойств. Это точно? И если так, как это работает?

Для начала, как он получает доступ к PIA? Он только смотрит на загруженные в настоящий момент PIA или динамически загружает их (и если да, то как)? Как это определяет, какой интерфейс, из которых может быть много, перечислить свойства? Кажется, он использует только один, а не обязательно первый. Из документации API, с которой я работаю (ArcObjects), интерфейс по умолчанию для этих объектов IUnknown так что это не просто использование интерфейса по умолчанию.

В примере на скриншотах интерфейс, в котором перечисляются члены, является IEnvelope интерфейс, который наследует от IGeometry интерфейс. Как VS2010 знает не перечислять членов IGeometry вместо этого, что, в моем тестировании, появляется первым, если вы просто перечислите все типы интерфейсов в PIA? Что-то очень умное происходит или, может быть, я упускаю что-то очевидное?

Причина, по которой я спрашиваю, заключается в том, что разработчик LINQPad, похоже, готов реализовать ту же функциональность, если бы он знал, как это делает VS. Таким образом, хороший ответ здесь может помочь улучшить этот очень популярный инструмент.

1 ответ

Вот как это сделать:

  • получить COM-объект IDispatch (альтернативный возможный путь IDispatchEx)
  • получить ссылку на библиотеку типов - IDispatch::GetTypeInfo
  • загрузить библиотеку типов и перечислить свойства
  • запросить у реального объекта значения для обнаруженных свойств

Применяются дополнительные дополнительные возможности: запрос IPersist* семейство интерфейсов или IProvideClassInfo в качестве альтернативы получить ссылку на библиотеку типов для объекта и открыть свойства.

Другие вопросы по тегам