Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Шаблон расширяемого объекта используется для расширения существующих классов среды выполнения с новыми функциями или добавления нового состояния в объект. Расширения, подключенные к одному из расширяемых объектов, обеспечивают поведение на очень разных этапах обработки для доступа к общему состоянию и функциональным возможностям, подключенным к общему расширяемым объекту, к которому они могут получить доступ.
Шаблон IExtensibleObject<T>
Существует три интерфейса в расширяемом шаблоне объектов: IExtensibleObject<T>, IExtension<T>и IExtensionCollection<T>.
Интерфейс IExtensibleObject<T> реализуется типами, позволяющими IExtension<T> объектам настраивать их функциональные возможности.
Расширяемые объекты позволяют динамически агрегировать IExtension<T> объекты. IExtension<T> Объекты характеризуются следующим интерфейсом:
public interface IExtension<T>
where T : IExtensibleObject<T>
{
void Attach(T owner);
void Detach(T owner);
}
Ограничение типа гарантирует, что расширения могут быть определены только для классов, которые являются IExtensibleObject<T>. Attach и Detach предоставляют уведомление об агрегировании или дезагрегировании.
Это приемлемо для реализаций ограничивать условия, при которых они могут быть добавлены или удалены у владельца. Например, вы можете полностью запретить удаление, запрещая добавлять или удалять расширения, когда владелец или расширение находятся в определенном состоянии, запрещать добавлять к нескольким владельцам одновременно или разрешать только одно добавление, за которым следует одно удаление.
IExtension<T> не подразумевает никаких взаимодействий с другими стандартными управляемыми интерфейсами. В частности, IDisposable.Dispose метод объекта владельца обычно не отсоединяет его расширения.
При добавлении расширения в коллекцию Attach вызывается перед добавлением в коллекцию. Когда расширение удаляется из коллекции, Detach вызывается после его удаления. Это означает , что (при условии соответствующей синхронизации) расширение может рассчитывать только на то, что оно найдено в коллекции, пока оно находится между Attach и Detach.
Объект, переданный FindAll или Find не должен быть IExtension<T> (например, можно передать любой объект), но возвращенное расширение является объектом IExtension<T>.
Если расширение в коллекции не является IExtension<T>, Find возвращает значение NULL и FindAll возвращает пустую коллекцию. Если несколько расширений реализуют IExtension<T>, Find возвращает одно из них. Возвращаемое из FindAll значение является снимком состояния.
Существует два основных сценария. Первый сценарий использует Extensions свойство в качестве словаря на основе типов для вставки состояния объекта, чтобы разрешить другому компоненту искать его с помощью типа.
Во втором сценарии используются Attach свойства и Detach свойства, позволяющие объекту участвовать в пользовательском поведении, таком как регистрация событий, просмотр переходов состояния и т. д.
Интерфейс IExtensionCollection<T> представляет собой коллекцию объектов IExtension<T>, которые позволяют извлекать IExtension<T> по его типу. IExtensionCollection<T>.Find возвращает последний добавленный объект, который является объектом IExtension<T> этого типа.
Расширяемые объекты в Windows Communication Foundation
В Windows Communication Foundation (WCF) есть четыре расширяемых объекта:
ServiceHostBase — это базовый класс для хоста службы. Расширения этого класса можно использовать для расширения поведения ServiceHostBase самой службы или хранения состояния для каждой службы.
InstanceContext — этот класс подключает экземпляр типа службы к среде выполнения службы. Он содержит сведения об экземпляре, а также ссылку на InstanceContextсодержащий ServiceHostBaseобъект. Расширения этого класса можно использовать для расширения поведения InstanceContext или хранения состояния для каждой службы.
OperationContext — Этот класс представляет сведения об операции, собираемые средой выполнения для каждой операции. Сюда входят такие сведения, как заголовки входящих сообщений, свойства входящих сообщений, входящие удостоверения безопасности и другие сведения. Расширения этого класса могут расширить поведение OperationContext или сохранить состояние для каждой операции.
IContextChannel — этот интерфейс позволяет проверять каждое состояние для каналов и прокси-серверов, созданных средой выполнения WCF. Расширения этого класса могут расширить поведение IClientChannel или использовать его для хранения состояния для каждого канала.
В следующем примере кода показано использование простого расширения для отслеживания InstanceContext объектов.
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace Microsoft.WCF.Documentation
{
public class MyInstanceContextInitializer : IInstanceContextInitializer
{
public void Initialize(InstanceContext instanceContext, Message message)
{
MyInstanceContextExtension extension = new MyInstanceContextExtension();
//Add your custom InstanceContext extension that will let you associate state with this instancecontext
instanceContext.Extensions.Add(extension);
}
}
//Create an Extension that will attach to each InstanceContext and let it retrieve the Id or whatever state you want to associate
public class MyInstanceContextExtension : IExtension<InstanceContext>
{
//Associate an Id with each Instance Created.
string _instanceId;
public MyInstanceContextExtension()
{ _instanceId = Guid.NewGuid().ToString(); }
public string InstanceId => _instanceId;
public void Attach(InstanceContext owner)
{
Console.WriteLine("Attached to new InstanceContext.");
}
public void Detach(InstanceContext owner)
{
Console.WriteLine("Detached from InstanceContext.");
}
}
public class InstanceInitializerBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters)
{ }
//Apply the custom IInstanceContextProvider to the EndpointDispatcher.DispatchRuntime
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
{
MyInstanceContextInitializer extension = new MyInstanceContextInitializer();
endpointDispatcher.DispatchRuntime.InstanceContextInitializers.Add(extension);
}
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
{ }
public void Validate(ServiceEndpoint endpoint)
{ }
}
public class InstanceInitializerBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(InstanceInitializerBehavior); }
}
protected override object CreateBehavior()
{
return new InstanceInitializerBehavior();
}
}
}