Расширяемые объекты
Шаблон расширяемого объекта используется для расширения существующих классов среды выполнения при помощи новых функций или добавления нового состояния к объекту. Расширения, привязанные к одному из расширяемых объектов, позволяют использовать поведения на различных этапах обработки для получения доступа к общему состоянию и функциональности, привязанным к общему расширяемому объекту, к которому они могут получить доступ.
Шаблон IExtensibleObject<T>
Предусмотрено три интерфейса в шаблоне расширяемого объекта: IExtensibleObject, IExtension и IExtensionCollection.
Интерфейс IExtensibleObject реализуется типами, которые позволяют объектам IExtension настроить свою функциональность.
Расширяемые объекты обеспечивают динамическое агрегирование объектов IExtension. Объекты IExtension характеризуются следующим интерфейсом.
public interface IExtension<T>
where T : IExtensibleObject<T>
{
void Attach(T owner);
void Detach(T owner);
}
Ограничение типов гарантирует, что расширения можно определить только для классов IExtensibleObject. Методы Attach и Detach предоставляют уведомление об агрегировании или деагрегировании.
Реализации могут ограничивать, если их можно добавить и удалить из владельца. Например, можно полностью запретить удаление, запретить добавление или удаление расширений, когда владелец или расширение находится в определенном состоянии, запретить одновременное добавление в несколько владельцев или разрешить только одно добавление с последующим одним удалением.
В шаблоне IExtension не подразумевается никаких взаимодействий с другими стандартными управляемыми интерфейсами. В частности, метод System.IDisposable.Dispose в объекте владельца, как правило, не отсоединяет его расширения.
При добавлении расширения в коллекцию метод Attach вызывается до того, как она поступает в коллекцию. При удалении расширения из коллекции метод Detach вызывается после ее удаления. Это значит (предполагая соответствующую синхронизацию), что расширение можно найти в коллекции, только в промежутке времени между вызовом метода Attach и метода Detach.
Нет необходимости, чтобы объект, переданный методу FindAll или методу Find, был объектом IExtension (например, можно передать любой объект), но возвращенное расширение должно быть расширением IExtension.
Если ни одно из расширений в коллекции не является расширением IExtension, метод Find возвращает значение null, а метод FindAll возвращает пустую коллекцию. Если несколько расширений реализуют IExtension, метод Find возвращает одно из них. Значение, возвращаемое методом FindAll, является моментальным снимком.
Имеется два основных сценария. В первом сценарии свойство Extensions используется как основанный на типах словарь для вставки состояния в объект с целью предоставления другому компоненту возможности просматривать его с помощью типа.
Во втором сценарии свойства Attach и Detach используются для предоставления объекту возможности участвовать в пользовательском поведении, таком как регистрация событий, наблюдение за переходами между состояниями и т. д.
Интерфейс IExtensionCollection представляет собой коллекцию объектов IExtension, обеспечивающих извлечение объекта IExtension его типом. Метод System.ServiceModel.IExtensionCollection.Find возвращает последний добавленный объект, являющийся объектом IExtension этого типа.
Расширяемые объекты в Windows Communication Foundation
Существует четыре расширяемых объекта в Windows Communication Foundation (WCF).
ServiceHostBase. Это базовый класс для узла службы. Расширения этого класса можно использовать для расширения поведения самого класса ServiceHostBase или для хранения состояния для каждой службы.
InstanceContext. Этот класс соединяет экземпляр типа службы и среду выполнения службы. В нем содержится информация об экземпляре, а также ссылка на класс ServiceHostBase, содержащий класс InstanceContext. Расширения этого класса можно использовать для расширения поведения самого класса InstanceContext или для хранения состояния для каждой службы.
OperationContext. Этот класс представляет данные об операциях, собранные средой выполнения для каждой операции. Сюда входят такие данные как заголовки входящих сообщений, свойства входящих сообщений, идентификация входящих сообщений и др. Расширения этого класса можно использовать как для расширения поведения класса OperationContext, так и для хранения состояния для каждой операции.
IContextChannel. Этот интерфейс обеспечивает проверку каждого состояния для каналов и прокси-серверов, созданных в среде выполнения WCF. Расширения этого класса можно использовать как для расширения поведения класса IClientChannel, так и для хранения состояния для каждого канала.
В следующем примере кода показано использование простого расширения для отслеживания объектов InstanceContext.