Rozšiřitelné objekty

Rozšiřitelný vzor objektu se používá k rozšíření existujících tříd modulu runtime s novými funkcemi nebo k přidání nového stavu do objektu. Rozšíření připojená k jednomu z rozšiřitelných objektů umožňují chování ve velmi různých fázích zpracování pro přístup ke sdílenému stavu a funkcím připojeným k běžnému rozšiřitelnému objektu, ke kterému mají přístup.

Vzor T objektu> IExtensibleObject<

V rozšiřitelném objektovém vzoru existují tři rozhraní: IExtensibleObject<T>, IExtension<T>a IExtensionCollection<T>.

Rozhraní IExtensibleObject<T> je implementováno pomocí typů, které umožňují IExtension<T> objektům přizpůsobit jejich funkce.

Rozšiřitelné objekty umožňují dynamickou agregaci IExtension<T> objektů. IExtension<T> objekty jsou charakterizovány následujícím rozhraním:

public interface IExtension<T>
where T : IExtensibleObject<T>
{
    void Attach(T owner);
    void Detach(T owner);
}

Omezení typu zaručuje, že rozšíření lze definovat pouze pro třídy, které jsou IExtensibleObject<T>. Attach a Detach uveďte oznámení o agregaci nebo členěné agregaci.

Platí pro implementace, které mohou být přidány a odebrány od vlastníka. Odebrání můžete například úplně zakázat, zakázat přidávání nebo odebírání rozšíření, pokud je vlastník nebo rozšíření v určitém stavu, zakážete přidávání více vlastníků současně nebo povolíte pouze jeden doplněk následovaný jedním odebráním.

IExtension<T> neznamená žádné interakce s jinými standardními spravovanými rozhraními. Konkrétně metoda IDisposable.Dispose u objektu vlastníka obvykle neodpojila jeho rozšíření.

Když je do kolekce přidáno rozšíření, je volána před tím, Attach než přejde do kolekce. Když je rozšíření odebráno z kolekce, Detach je volána po jeho odebrání. To znamená ,že (za předpokladu vhodné synchronizace) se rozšíření může spolehnout pouze na to, že se v kolekci nachází, zatímco je mezi Attach a Detach.

Objekt předaný FindAll nebo Find nemusí být IExtension<T> (například můžete předat jakýkoli objekt), ale vrácené rozšíření je .IExtension<T>

Pokud v kolekci IExtension<T>není žádné rozšíření , Find vrátí hodnotu null a FindAll vrátí prázdnou kolekci. Pokud implementujete IExtension<T>více rozšíření, Find vrátí jednu z nich. Vrácená hodnota FindAll je snímek.

Existují dva hlavní scénáře. První scénář používá Extensions vlastnost jako slovník založený na typu k vložení stavu do objektu, aby další komponenta mohla vyhledat pomocí typu.

Druhý scénář používá vlastnosti Attach a Detach umožňuje objektu účastnit se vlastního chování, jako je registrace událostí, sledování přechodů stavu atd.

Rozhraní IExtensionCollection<T> je kolekce IExtension<T> objektů, které umožňují načtení IExtension<T> podle jeho typu. IExtensionCollection<T>.Find vrátí naposledy přidaný objekt, který je daný IExtension<T> typ.

Rozšiřitelné objekty ve Službě Windows Communication Foundation

Ve Windows Communication Foundation (WCF) jsou čtyři rozšiřitelné objekty:

  • ServiceHostBase – Toto je základní třída hostitele služby. Rozšíření této třídy lze použít k rozšíření chování ServiceHostBase samotného nebo k uložení stavu pro každou službu.

  • InstanceContext – Tato třída připojí instanci typu služby s modulem runtime služby. Obsahuje informace o instanci a odkaz na InstanceContext"obsahující ServiceHostBase" . Rozšíření této třídy lze použít k rozšíření chování InstanceContext nebo uložení stavu pro každou službu.

  • OperationContext – Tato třída představuje informace o operaci, které modul runtime shromažďuje pro každou operaci. To zahrnuje informace, jako jsou hlavičky příchozí zprávy, vlastnosti příchozí zprávy, příchozí identita zabezpečení a další informace. Rozšíření této třídy mohou buď rozšířit chování OperationContext nebo uložit stav pro každou operaci.

  • IContextChannel – Toto rozhraní umožňuje kontrolu jednotlivých stavů pro kanály a proxy servery vytvořené modulem runtime WCF. Rozšíření této třídy mohou buď rozšířit chování IClientChannel , nebo ho může použít k uložení stavu pro každý kanál.

Následující příklad kódu ukazuje použití jednoduchého rozšíření ke sledování InstanceContext objektů.

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

Viz také