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