Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O padrão de objeto extensível é usado para estender classes de runtime existentes com novas funcionalidades ou para adicionar um 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 que IExtension<T> os objetos personalizem suas funcionalidades.
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ó possam ser definidas para classes que são IExtensibleObject<T>. Attach e Detach fornecem uma 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 inteiramente, não permitindo adicionar ou remover extensões quando o proprietário ou a extensão estiver em um determinado estado, não permitir a adição a vários proprietários simultaneamente ou permitir apenas uma única adição seguida por uma única remoção.
IExtension<T> não implica nenhuma interações com outras interfaces gerenciadas padrão. Especificamente, o IDisposable.Dispose método no objeto proprietário 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 removida. Isso significa (supondo a sincronização apropriada) que uma extensão pode contar com ser encontrada na coleção somente 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>.
Se nenhuma extensão na coleção for um IExtension<T>, Find retornará nulo e FindAll retornará uma coleção vazia. Se várias extensões forem implementadas IExtension<T>, Find retornará uma delas. O valor retornado de FindAll é um instantâneo.
Há 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 a procure usando o tipo.
O segundo cenário usa as propriedades Attach e Detach para permitir que um objeto participe de um comportamento personalizado, como registrar-se em eventos, assistir a transições de estado e assim por diante.
A interface IExtensionCollection<T> é uma coleção de objetos IExtension<T> que permite a recuperação de IExtension<T> pelo seu tipo. IExtensionCollection<T>.Find retorna o objeto adicionado mais recentemente que é um IExtension<T> desse tipo.
Objetos extensíveis no Windows Communication Foundation
Há quatro objetos extensíveis no Windows Communication Foundation (WCF):
ServiceHostBase – Essa é a classe base para o host do serviço. Extensões dessa classe podem ser usadas para estender o comportamento de ServiceHostBase si mesmo ou armazenar o estado para cada serviço.
InstanceContext – Essa classe conecta uma instância do tipo do serviço com o runtime do serviço. Ela contém informações sobre a instância, bem como uma referência aos InstanceContexts que contêm ServiceHostBase. Extensões dessa classe podem ser usadas para estender o comportamento do InstanceContext ou armazenar o estado de cada serviço.
OperationContext – Essa classe representa as informações de operação coletadas pelo runtime para cada operação. Isso inclui informações como os cabeçalhos de mensagem de entrada, as propriedades da mensagem de entrada, a identidade de segurança de entrada e outras informações. As extensões dessa classe podem estender o comportamento de OperationContext ou armazenar o estado de cada operação.
IContextChannel – Essa interface permite a inspeção de cada estado para os canais e proxies criados pelo runtime do WCF. As extensões dessa classe podem estender o comportamento IClientChannel ou usá-lo para armazenar o estado de 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.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();
}
}
}