Программирование >>  Дополнения add-ins 

1 2 [ 3 ] 4 5 6 7


6. Конструируется экземпляр адаптера стороны хоста в домене принимающего приложения. Прокси адаптера стороны дополнения передается конструктору. Активизация находит тип адаптера стороны хоста из маркера дополнения.

Адаптер стороны хоста возвращается принимающему приложению.

Контракты

Контракты определяют границы между стороной хоста и стороной дополнения. Контракты определяются интерфейсом, который должен наследоваться от базового интерфейса IContract. Контракт должен быть тщательно продуман, чтобы обеспечить необходимую гибкость сценариев применения дополнений.

Контракты не имеют версий и могут не изменяться, так что предыдущие реализации дополнения могут запускаться на более новых хостах. Новые версии создаются определением нового контракта.

Существуют некоторые ограничения типов, которые вы можете использовать с контрактом. Они обусловлены сложностями, связанными с версиями, а также пересечением доменов приложений хоста и дополнения. Типы должны быть безопасными и согласованными по версиям, а также иметь возможность преодолевать границы (доменов приложений или процессов), чтобы передаваться между хостами и дополнениями.

Допустимые типы, которые могут передаваться с контрактом:

□ примитивные типы;

□ другие контракты;

□ сериализуемые системные типы;

□ простые сериализуемые специальные типы, состоящие из примитивных типов, контрактов и не имеющие реализации.

Члены интерфейса IContract описаны в табл. 36.5. Таблица 36.5. Члены интерфейса IContract

Член IContract Описание

QueryContract() С помощью QueryContract() можно запросить контракт прове-

рить, реализован ли также другой контракт. Дополнение может поддерживать несколько контрактов.

RemoteToString() Параметр QueryContract() требует строкового представления

контракта. RemoteToString() возвращает строковое представление текущего контракта.

AcquireLifetimeToken() Клиент вызывает AcquireLifetimeToken() для сохранения ссылки RevokeLifetimeToken() на контракт. AcquireLifetimeToken() увеличивает счетчик ссылок. RevokeLifetimeToken() уменьшает счетчик ссылок.

RemoteEquals() RemoteEquals() может использоваться для сравнения двух ссылок

на контракты.

Интерфейсы контрактов определены в пространстве имен System.AddIn. Contract, System.AddIn.Contract.Collections и System.AddIn.Contract. Automation. В табл. 36.6 перечислены интерфейсы контрактов, которые вы можете использовать с контрактом.



Таблица 36.6. Интерфейсы контрактов

Контракт Описание

IListContract<T> IListContract<T> может использоваться для возврата списка

контрактов.

IEnumeratorContract<T> IEnumeratorContract<T> применяется для перечисления элементов IListContract<T>.

IServiceProviderContract Дополнение может предоставлять службы другим дополнениям.

Дополнение, предоставляющее службу, называется поставщиком

службы и реализует интерфейс IServiceProviderContract.

Посредством метода QueryService() дополнение, реализующее этот интерфейс, может быть опрошено на предмет предоставляемых служб.

IProfferServiceContract IProfferServiceContract - интерфейс, предоставляемый поставщиком службы в сочетании с IServiceProviderContract. Интерфейс IProfferServiceContract определяет методы ProfferService() и RevokeService(). Метод ProfferService() добавляет IServiceProviderContract к предоставляемым службам, а RevokeService() удаляет его.

INativeHandleContract Этот интерфейс предоставляет доступ к родным дескрипторам

Windows через метод GetHandle(). Этот контракт применяется с хостами WPF для использования дополнений WPF.

Жизненный цикл

Насколько долго дополнение должно пребывать в загруженном состоянии? Сколько времени оно используется? Когда можно выгрузить домен приложения? Есть несколько вариантов разрешения этих вопросов. Один вариант заключается в использовании счетчика ссылок. Каждое использование дополнения увеличивает значение счетчика. Когда значение счетчика уменьшается до нуля, дополнение может быть выгружено. Другой вариант - применять сборщик мусора. Если запускается сборщик мусора, и на объект не остается никаких ссылок, то этот объект подлежит уничтожению сборщиком. .NET Remoting использует механизм аренды и спонсорства для удержания объектов в живом состоянии. Как только истекает время аренды, спонсоры запрашивают, должен ли объект оставаться живым.

Что касается дополнений, здесь возникает определенная сложность с выгрузкой, потому что они могут запускаться в разных доменах приложений и разных процессах. Сборщик мусора не может работать через границы процессов. MAF использует смешанную модель для управления жизненным циклом. В пределах одного домена приложения используется сборщик мусора. В пределах канала применяется неявное спонсорство, но счетчик ссылок доступен извне для контроля спонсора.

Рассмотрим сценарий, когда дополнение загружается в другой домен приложения. Внутри принимающего приложения (хоста) сборщик мусора очищает представление хоста и адаптер стороны хоста, когда надобность в ссылке отпадает. Для стороны дополнения контракт определяет методы AcquireLifetimeToken() и RevokeLifetimeToken() для увеличения и уменьшения значения, которое может привести к слишком раннему освобождению объекта, если одна часть станет вызывать метод revoke слишком части. Вместо этого AcquireLifetimeToken() возвращает идентификатор маркера жизненного цикла, и этот идентификатор должен быть использован для вызова метода RevokeLifetimeToken() . Таким образом, эти методы всегда вызываются парами.



Обычно вам не придется иметь дело с методами AcquireLifetimeToken() и RevokeLifetimeToken(). Вместо этого вы можете использовать класс ContractHandle, вызывающий AcquireLifetimeToken() в конструкторе и RevokeLifetimeToken() - в финализаторе.

Финализатор объясняется в главе 12.

В сценариях с загрузкой дополнения в новый домен приложения можно избавиться от загруженного кода, когда дополнение уже не нужно. MAF использует простую модель для определения одного дополнения на домен приложения, чтобы выгружать его, когда необходимость в дополнении отпадает. Дополнение выступает владельцем домена приложения, если домен приложения создается при активизации дополнения. Домен приложения не выгружается автоматически, если он был создан ранее.

Класс ContractHandle используется в адаптере стороны хоста для добавления счетчика ссылки на дополнение. Члены этого класса описаны в табл. 36.7.

Таблица 36.7. Члены ContractHandle

Член ContractHandle Описание

Contract При конструировании класса ContractHandle объект, реализую-

щий IContract, может быть присвоен для сохранения ссылки на него. Свойство Contract возвращает этот объект.

Dispose() Метод Dispose() может быть вызван вместо ожидания, когда

сборщик мусора выполнит финализацию для аннулирования маркера жизненного цикла.

AppDomainOwner() AppDomainOwner() - статический метод класса

ContractHandle, возвращающий адаптер дополнения, если он владеет доменом приложения, переданным в этот метод.

ContractOwnsAppDomain() С помощью статического метода ContractOwnsAppDomain()

вы можете проверить, является ли специфицированный контракт владельцем домена приложения. Таким образом, домен приложения выгружается при освобождении контракта.

Поддержка версий

Поддержка версий является очень большой проблемой для дополнений. Принимающее приложение разрабатывается заранее с учетом будущих дополнений. К дополнению предъявляется требование, чтобы была возможность загрузки старых версий дополнения новыми версиями приложения. Также эта пара должна работать и в противоположном направлении: старые приложения должны запускать новые версии дополнений. Но что, если изменится контракт?

System.AddIn полностью независим от реализаций хост-приложения и дополнений. Это обеспечивается концепцией канала, состоящего из семи частей.

Пример дополнения

Начнем с простого примера принимающего приложения, которое может загружать дополнения калькулятора. Дополнения могут поддерживать разные вычислительные операции, предоставленные дополнениями.

Вам нужно создать решение с шестью проектами библиотек и одним консольным приложением. Проекта: простого приложения представлены в табл. 36.8. В таблице



1 2 [ 3 ] 4 5 6 7

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.076
При копировании материалов приветствуются ссылки.
Яндекс.Метрика