Sdílet prostřednictvím


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 poskytují oznámení o agregaci nebo deagregaci.

Je platné, že implementace mohou mít omezení, kdy mohou být přidány a odebrány od vlastníka. Například můžete úplně zakázat odebrání, 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ázat současně přidávat jednomu vlastníkovi více rozšíření, nebo povolit pouze jedno přidání následované jedním odebráním.

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

Když je rozšíření přidáno do kolekce, Attach je voláno před tím, než přejde do kolekce. Když je rozšíření odebráno z kolekce, Detach je zavoláno po jeho odebrání. To znamená, že (za předpokladu vhodné synchronizace) se rozšíření může spolehnout pouze na to, že se nachází v kolekci, 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 více rozšíření implementuje IExtension<T>, Find vrátí jedno z nich. Vrácená hodnota FindAll je snímek.

Existují dva hlavní scénáře. První scénář používá vlastnost Extensions jako slovník založený na typech pro vložení stavu do objektu, což umožní jiné komponentě ho 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 této kategorie IExtension<T>.

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 také odkaz na InstanceContext, který obsahuje 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, identita přicházejícího 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.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();
        }
    }
}

Viz také