Delen via


Uitbreidbare objecten

Het uitbreidbare objectpatroon wordt gebruikt om bestaande runtimeklassen uit te breiden met nieuwe functionaliteit of om nieuwe status toe te voegen aan een object. Extensies die zijn gekoppeld aan een van de uitbreidbare objecten, maken gedrag mogelijk in zeer verschillende fasen in de verwerking om toegang te krijgen tot de gedeelde status en functionaliteit die is gekoppeld aan een gemeenschappelijk uitbreidbaar object waartoe ze toegang hebben.

Het IExtensibleObject T-patroon<>

Er zijn drie interfaces in het uitbreidbare objectpatroon: IExtensibleObject<T>, IExtension<T>en IExtensionCollection<T>.

De IExtensibleObject<T> interface wordt geïmplementeerd door typen waarmee IExtension<T> objecten hun functionaliteit kunnen aanpassen.

Uitbreidbare objecten maken dynamische aggregatie van IExtension<T> objecten mogelijk. IExtension<T> objecten worden gekenmerkt door de volgende interface:

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

De typebeperking garandeert dat extensies alleen kunnen worden gedefinieerd voor klassen die .IExtensibleObject<T> Attach en Detach geef een melding van aggregatie of aggregatie.

Het is geldig voor implementaties om te beperken wanneer ze kunnen worden toegevoegd en verwijderd van een eigenaar. U kunt bijvoorbeeld het verwijderen helemaal niet toestaan, het toevoegen of verwijderen van extensies ongedaan maken wanneer de eigenaar of extensie zich in een bepaalde staat bevindt, het gelijktijdig toevoegen van meerdere eigenaren niet toestaan of slechts één toevoeging toestaan, gevolgd door één verwijderbewerking.

IExtension<T> impliceert geen interacties met andere standaard beheerde interfaces. Met name de IDisposable.Dispose methode voor het eigenaarobject koppelt de extensies normaal gesproken niet los.

Wanneer een extensie wordt toegevoegd aan de verzameling, Attach wordt deze aangeroepen voordat deze in de verzameling wordt opgenomen. Wanneer een extensie uit de verzameling wordt verwijderd, Detach wordt deze aangeroepen nadat deze is verwijderd. Dit betekent (ervan uitgaande dat de juiste synchronisatie) een extensie alleen kan worden gevonden in de verzameling terwijl deze zich tussen Attach en Detach.

Het object dat is doorgegeven aan FindAll of Find niet hoeft te zijn IExtension<T> (u kunt bijvoorbeeld elk object doorgeven), maar de geretourneerde extensie is een IExtension<T>.

Als er geen extensie in de verzameling is IExtension<T>, Find wordt null geretourneerd en FindAll wordt een lege verzameling geretourneerd. Als meerdere extensies worden geïmplementeerd IExtension<T>, Find wordt een van deze extensies geretourneerd. De geretourneerde FindAll waarde is een momentopname.

Er zijn twee hoofdscenario's. In het eerste scenario wordt de Extensions eigenschap gebruikt als een op een type gebaseerde woordenlijst om de status van een object in te voegen, zodat een ander onderdeel deze kan opzoeken met behulp van het type.

In het tweede scenario worden de Attach en Detach eigenschappen gebruikt om een object in staat te stellen deel te nemen aan aangepast gedrag, zoals het registreren voor gebeurtenissen, het bekijken van statusovergangen, enzovoort.

De IExtensionCollection<T> interface is een verzameling van de IExtension<T> objecten waarmee het IExtension<T> type kan worden opgehaald. IExtensionCollection<T>.Find retourneert het laatst toegevoegde object dat een IExtension<T> van dat type is.

Uitbreidbare objecten in Windows Communication Foundation

Er zijn vier uitbreidbare objecten in Windows Communication Foundation (WCF):

  • ServiceHostBase – Dit is de basisklasse voor de host van de service. Extensies van deze klasse kunnen worden gebruikt om het gedrag van het ServiceHostBase zelf uit te breiden of om de status voor elke service op te slaan.

  • InstanceContext – Deze klasse verbindt een exemplaar van het servicetype met de serviceruntime. Het bevat informatie over het exemplaar en een verwijzing naar de InstanceContext's die bevatten ServiceHostBase. Extensies van deze klasse kunnen worden gebruikt om het gedrag van de InstanceContext service uit te breiden of om de status voor elke service op te slaan.

  • OperationContext – Deze klasse vertegenwoordigt de bewerkingsgegevens die de runtime verzamelt voor elke bewerking. Dit omvat informatie zoals de binnenkomende berichtkoppen, de eigenschappen van het binnenkomende bericht, de binnenkomende beveiligingsidentiteit en andere informatie. Extensies van deze klasse kunnen het gedrag van of het opslaan van OperationContext de status voor elke bewerking uitbreiden.

  • IContextChannel – Met deze interface kan elke status worden gecontroleerd voor de kanalen en proxy's die zijn gebouwd door de WCF-runtime. Extensies van deze klasse kunnen het gedrag van IClientChannel deze klasse uitbreiden of gebruiken om de status voor elk kanaal op te slaan.

In het volgende codevoorbeeld ziet u het gebruik van een eenvoudige extensie om objecten bij te houden InstanceContext .

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

Zie ook