Контракты, представления и адаптеры
Обновлен: Ноябрь 2007
В этом разделе обсуждаются представления и адаптеры — сегменты, которые используются на обеих сторонах конвейера надстройки, а также контракты, которые используются как основным приложением, так и надстройкой. На следующем рисунке показаны сегменты конвейера надстройки.
Конвейер надстройки
Примеры кода см. в разделах Пошаговое руководство. Включение обратной совместимости при изменении основного приложения и Пошаговое руководство. Передача коллекций между основными приложениями и надстройками.
Контракты
Первым шагом разработки конвейера взаимодействия является определение контракта, который должен быть производным из интерфейса IContract. Если основное приложение и надстройка загружены в различные домены приложения, между стороной надстройки и стороной основного приложения в используемом конвейере существует граница изоляции. Контракт — это интерфейс без версии, который определяет протокол для типов взаимодействия через границу изоляции. Используя контракты для взаимодействия через границы изоляции, модель надстройки предотвращает утечку реализаций типов как основного приложения, так и надстройки, через границы, предотвращая тем самым проблемы, связанные с версиями.
Объекты, которые должны взаимодействовать в разных доменах приложения должны поддерживать удаленное взаимодействие. Дополнительные сведения об объектах, поддерживающих удаленное взаимодействие, см. в разделе Remotable and Nonremotable Objects.
Класс ContractBase предоставляет реализацию элементов IContract по умолчанию. Интерфейс контракта также может наследовать этот класс.
Требования к контрактам
Контракты должны придерживаться набора требований для обеспечения безопасности всех типов, выраженных в контрактах, использования различных версий и возможности передачи через границы изоляции между основными приложениями и надстройками.
Контракты должны наследовать из IContract и использовать только следующие типы:
Прочие контракты, производные из IContract.
Примитивные типы данных: целые числа и логические значения.
Сериализуемые типы, определенные в сборке контракта.
Сериализуемые значения, определенные в Mscorlib.dll, такие как Int32 и DateTime.
Запечатанные сериализуемые ссылочные типы. Например, можно передать объект String за пределы границы изоляции, так как он запечатан, сериализован и является ссылочным типом.
Перечисления, определенные в контракте или в Mscorlib.dll.
Объекты AddInToken.
Массивы, состоящие из приведенных выше типов, кроме массива контрактов.
Чтобы передать коллекции объектов, используйте типы, которые реализуют универсальный интерфейс IList<T>, например коллекции List<T> и ArrayList. Чтобы передать эти коллекции за пределы границы изоляции, необходимо временно преобразовать их в интерфейс IListContract<T>. В разделе Пошаговое руководство. Передача коллекций между основными приложениями и надстройками показано, как передавать коллекции.
Чтобы сконструировать конвейер, необходимо идентифицировать контракт, представляющий надстройку, с помощью атрибута AddInContractAttribute.
Следующим действием при разработке конвейера является создание сегментов представления и адаптера для обеих сторон конвейера. Эти сегменты предоставляют основному приложению и надстройке представления соответствующих моделей объектов, а также предоставляют адаптеры, которые преобразуют эти представления в контракт и наоборот.
Представления
Представление надстройки, относящееся к основному приложению, и представление основного приложения, относящееся к надстройке, являются сборками, которые содержат интерфейсы или абстрактные классы, представляющие представления как друг друга, так и типов, которые передаются между ними. Представления не зависят от контрактов, используемых для взаимодействия. Представления также отделяют надстройку и основное приложение от их реализаций. Это позволяет адаптерам и контракту изменяться без влияния на основное приложение и надстройку.
Для построения конвейера, тип в представлении надстройки, который надстройка реализует или наследует, идентифицируется атрибутом AddInBaseAttribute и называется базой надстройки. Представление основного приложения не нуждается в атрибуте обнаружения, потому что представление основного приложения передается в методы FindAddIns.
Адаптеры
Адаптеры на стороне надстройки и на стороне основного приложения являются сборками, содержащими классы адаптеров, которые используются для преобразования представлений в контракт и наоборот. Термин "на стороне" относится к стороне конвейера, на которой расположен адаптер. В зависимости от направления вызова адаптер выполняет преобразование либо из представления в контракт, либо из контракта в представление. Если вызовы происходят в обоих направлениях (то есть основное приложение вызывает надстройку, а надстройка вызывает основное приложение) на двух сторонах конвейера будут расположены два адаптера. Соответственно, существуют два типа адаптеров:
Адаптер "представление-контракт".
Класс в сборке адаптера, который преобразует представление в контракт. Этот класс реализует контракт посредством вызова представления, переданного в конструктор и маршалированного через границу в виде контракта. Этот класс должен наследовать ContractBase и реализовать контракт.
Адаптер "контракт-представление".
Класс в сборке адаптера, который преобразует контракт в представление. Этот класс реализует или наследует сегмент преобразуемого представления в зависимости от того, является ли это представлением интерфейсом или абстрактным базовым типом, и реализует элементы представления посредством вызова контракта, переданного в конструктор адаптера.
Чтобы сконструировать конвейер, необходимо идентифицировать класс адаптера на стороне надстройки посредством применения атрибута AddInAdapterAttribute, а также идентифицировать класс адаптера на стороне основного приложения посредством применения атрибута HostAdapterAttribute.
Адаптеры не обязательно должны быть открытыми.