Objetos extensíveis
O padrão de objeto extensível é usado para estender classes de tempo de execução existentes com nova funcionalidade ou para adicionar novo estado a um objeto. As extensões, anexadas a um dos objetos extensíveis, permitem comportamentos em estágios muito diferentes no processamento para acessar o estado compartilhado e a funcionalidade anexada a um objeto extensível comum que eles podem acessar.
O padrão IExtensibleObject<T>
Há três interfaces no padrão de objeto extensível: IExtensibleObject<T>, IExtension<T>e IExtensionCollection<T>.
A IExtensibleObject<T> interface é implementada por tipos que permitem IExtension<T> que os objetos personalizem sua funcionalidade.
Objetos extensíveis permitem a agregação dinâmica de IExtension<T> objetos. IExtension<T> Os objetos são caracterizados pela seguinte interface:
public interface IExtension<T>
where T : IExtensibleObject<T>
{
void Attach(T owner);
void Detach(T owner);
}
A restrição de tipo garante que as extensões só podem ser definidas para classes que são IExtensibleObject<T>. Attach e Detach fornecer notificação de agregação ou desagregação.
É válido que as implementações restrinjam quando podem ser adicionadas e removidas de um proprietário. Por exemplo, você pode não permitir a remoção totalmente, não permitir a adição ou remoção de extensões quando o proprietário ou a extensão estiverem em um determinado estado, não permitir a adição a vários proprietários simultaneamente ou permitir apenas uma única adição seguida de uma única remoção.
IExtension<T> não implica quaisquer interações com outras interfaces geridas padrão. Especificamente, o IDisposable.Dispose método no objeto owner normalmente não desanexa suas extensões.
Quando uma extensão é adicionada à coleção, Attach é chamada antes de entrar na coleção. Quando uma extensão é removida da coleção, Detach é chamada depois de ser removida. Isso significa (supondo a sincronização apropriada) que uma extensão pode contar apenas para ser encontrada na coleção enquanto estiver entre Attach e Detach.
O objeto passado para FindAll ou Find não precisa ser IExtension<T> (por exemplo, você pode passar qualquer objeto), mas a extensão retornada é um IExtension<T>arquivo .
Se nenhuma extensão na coleção for um IExtension<T>, Find retornará null e FindAll retornará uma coleção vazia. Se várias extensões implementarem IExtension<T>, Find retornará uma delas. O valor retornado de FindAll é um instantâneo.
Existem dois cenários principais. O primeiro cenário usa a Extensions propriedade como um dicionário baseado em tipo para inserir o estado em um objeto para permitir que outro componente o procure usando o tipo.
O segundo cenário usa as Attach propriedades e Detach para permitir que um objeto participe de um comportamento personalizado, como registrar-se para eventos, observar transições de estado e assim por diante.
A IExtensionCollection<T> interface é uma coleção de IExtension<T> objetos que permitem recuperar o IExtension<T> por seu tipo. IExtensionCollection<T>.Find Retorna o objeto adicionado mais recentemente que é desse IExtension<T> tipo.
Objetos extensíveis no Windows Communication Foundation
Há quatro objetos extensíveis no Windows Communication Foundation (WCF):
ServiceHostBase – Esta é a classe base para o host do serviço. Extensões dessa classe podem ser usadas para estender o comportamento da própria ou para armazenar o estado para ServiceHostBase cada serviço.
InstanceContext – Esta classe conecta uma instância do tipo do serviço com o tempo de execução do serviço. Ele contém informações sobre a instância, InstanceContextbem como uma referência ao .ServiceHostBase Extensões dessa classe podem ser usadas para estender o comportamento do InstanceContext ou para armazenar o estado para cada serviço.
OperationContext – Esta classe representa as informações da operação que o tempo de execução reúne para cada operação. Isso inclui informações como os cabeçalhos das mensagens de entrada, as propriedades das mensagens de entrada, a identidade de segurança de entrada e outras informações. As extensões dessa classe podem estender o comportamento ou armazenar o estado de OperationContext cada operação.
IContextChannel – Esta interface permite a inspeção de cada estado para os canais e proxies construídos pelo tempo de execução WCF. As extensões dessa classe podem estender o comportamento de ou podem usá-lo para armazenar o estado de IClientChannel cada canal.
O exemplo de código a seguir mostra o uso de uma extensão simples para rastrear InstanceContext objetos.
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Text;
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()
{ this.instanceId = Guid.NewGuid().ToString(); }
public String InstanceId
{
get
{ return this.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();
}
}
}