Partilhar via


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();
    }
  }
}

Consulte também