Маршалинг по умолчанию для классов
Обновлен: Ноябрь 2007
Маршалинг классов может выполняться только с помощью COM-взаимодействия и только в качестве интерфейсов. Иногда интерфейс, используемый для маршалинга класса, называют интерфейсом класса. Сведения о переопределении интерфейса класса интерфейсом, выбранным разработчиком, см. в разделе Введение в интерфейс классов.
Передача классов в COM-приложение
При передаче управляемого класса в COM-приложение упаковщик взаимодействия автоматически инкапсулирует этот класс, используя COM-прокси, и передает интерфейс класса, полученный с помощью прокси, в вызов COM-метода. Затем прокси делегирует все вызовы для интерфейса класса назад, в управляемый объект. Этот прокси также предоставляет другие интерфейсы, не реализуемые классом в явном виде. Прокси от имени класса автоматически реализует такие интерфейсы, как IUnknown и IDispatch.
Передача классов в код .NET
В COM-приложении компонентные классы обычно не используются в качестве аргументов метода. Вместо компонентного класса обычно передается интерфейс по умолчанию.
При передаче интерфейса в управляемый код упаковщик взаимодействия отвечает за инкапсуляцию интерфейса в соответствующую оболочку и за передачу этой оболочки в управляемый метод. Выбор используемой оболочки может вызывать затруднения. У каждого экземпляра COM-объекта есть одна уникальная оболочку вне зависимости от числа интерфейсов, реализуемых объектом. Например, COM-объект, реализующий пять различных интерфейсов, использует только одну оболочку. Одна и та же оболочка предоставляет все пять интерфейсов. При создании двух экземпляров COM-объекта создается два экземпляра оболочки.
Чтобы тип оболочки не менялся в течение всего времени ее существования, упаковщик взаимодействия должен выбрать правильную оболочку при первой передаче интерфейса, предоставляемого данным объектом, через упаковщик. Упаковщик идентифицирует объект, просматривая один из интерфейсов, реализуемых объектом.
Например, упаковщик определяет, что оболочка класса должна использоваться для инкапсуляции интерфейса, переданного в управляемый код. При первой передаче этого интерфейса через упаковщик последний проверяет, поступил ли этот интерфейс от известного объекта. При такой проверке возможны две ситуации:
Интерфейс реализуется другим управляемым объектом, переданным в COM-приложение где-то в другом месте. Упаковщик может легко идентифицировать интерфейсы, предоставляемые управляемыми объектами, и может находить соответствие между интерфейсом и управляемым объектом, предоставившим данную реализацию. Затем управляемый объект передается методу и никакой оболочки не требуется.
Интерфейс реализуется объектом, который уже инкапсулирован. Чтобы выявить подобную ситуацию, упаковщик запрашивает у объекта его интерфейс IUnknown и сравнивает возвращенный интерфейс с интерфейсами других, уже инкапсулированных объектов. Если этот интерфейс совпадает с интерфейсом другой оболочки, эти объекты имеют одинаковую идентификацию, и существующая оболочка передается методу.
Если интерфейс не является интерфейсом известного объекта, упаковщик выполняет следующие действия:
Упаковщик запрашивает у объекта наличие интерфейса IProvideClassInfo2. Если такой интерфейс предоставлен, упаковщик использует значение CLSID, возвращенное из IProvideClassInfo2.GetGUID, чтобы определить компонентный класс, предоставляющий данный интерфейс. Используя этот идентификатор CLSID, упаковщик может найти оболочку в реестре, если перед этим сборка была зарегистрирована.
Упаковщик запрашивает у этого интерфейса интерфейс IProvideClassInfo. Если этот интерфейс предоставлен, упаковщик использует ITypeInfo, возвращенный из IProvideClassInfo.GetClassinfo, чтобы определить идентификатор CLSID класса, предоставляющего интерфейса. Упаковщик может использовать значение CLSID, чтобы найти метаданные для оболочки.
Если упаковщик все еще не может идентифицировать данный класс, он инкапсулирует интерфейс в базовый класс-оболочку с именем System.__ComObject.
См. также
Основные понятия
Преобразуемые и непреобразуемые типы