Dela via


Utökningsbara objekt

Det utökningsbara objektmönstret används för att antingen utöka befintliga körningsklasser med nya funktioner eller för att lägga till nytt tillstånd i ett objekt. Tillägg, kopplade till ett av de utökningsbara objekten, möjliggör beteenden i mycket olika faser i bearbetningen för att få åtkomst till delat tillstånd och funktioner som är kopplade till ett gemensamt utökningsbart objekt som de kan komma åt.

IExtensibleObject<T-mönstret>

Det finns tre gränssnitt i det utökningsbara objektmönstret: IExtensibleObject<T>, IExtension<T>och IExtensionCollection<T>.

Gränssnittet IExtensibleObject<T> implementeras av typer som gör det möjligt IExtension<T> för objekt att anpassa sina funktioner.

Utökningsbara objekt tillåter dynamisk aggregering av IExtension<T> objekt. IExtension<T> objekt kännetecknas av följande gränssnitt:

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

Typbegränsningen garanterar att tillägg endast kan definieras för klasser som är IExtensibleObject<T>. Attach och Detach meddela aggregering eller disaggregering.

Det är giltigt för implementeringar att begränsa när de kan läggas till och tas bort från en ägare. Du kan till exempel inte tillåta borttagning helt och hållet, inte tillåta att tillägg läggs till eller tas bort när ägaren eller tillägget är i ett visst tillstånd, inte tillåter att flera ägare läggs till samtidigt eller endast tillåter ett enda tillägg följt av en enda borttagning.

IExtension<T> innebär inte några interaktioner med andra standardhanterade gränssnitt. IDisposable.Dispose Mer specifikt kopplar metoden på ägarobjektet normalt inte bort sina tillägg.

När ett tillägg läggs till i samlingen Attach anropas innan det hamnar i samlingen. När ett tillägg tas bort från samlingen Detach anropas när det har tagits bort. Det innebär att (förutsatt lämplig synkronisering) ett tillägg kan räkna med att endast hittas i samlingen när det är mellan Attach och Detach.

Objektet som skickas till FindAll eller behöver inte vara IExtension<T> (du kan till exempel skicka ett objekt), men det returnerade tillägget är ett IExtension<T>Find .

Om inget tillägg i samlingen är en IExtension<T>returnerar null Find och FindAll returnerar en tom samling. Om flera tillägg implementerar IExtension<T>Find returnerar en av dem. Värdet som returneras från FindAll är en ögonblicksbild.

Det finns två huvudscenarier. Det första scenariot använder egenskapen Extensions som en typbaserad ordlista för att infoga tillstånd på ett objekt för att göra det möjligt för en annan komponent att söka efter den med hjälp av typen .

Det andra scenariot använder Attach egenskaperna och Detach för att göra det möjligt för ett objekt att delta i anpassat beteende, till exempel registrering för händelser, titta på tillståndsövergångar och så vidare.

Gränssnittet IExtensionCollection<T> är en samling av de IExtension<T> objekt som gör det möjligt att hämta efter IExtension<T> dess typ. IExtensionCollection<T>.Find returnerar det senast tillagda objektet som är av IExtension<T> den typen.

Utökningsbara objekt i Windows Communication Foundation

Det finns fyra utökningsbara objekt i Windows Communication Foundation (WCF):

  • ServiceHostBase – Det här är basklassen för tjänstens värd. Tillägg för den här klassen kan användas för att utöka beteendet ServiceHostBase för sig själv eller för att lagra tillståndet för varje tjänst.

  • InstanceContext – Den här klassen ansluter en instans av tjänstens typ med tjänstkörningen. Den innehåller information om instansen samt en referens till de InstanceContextsom innehåller ServiceHostBase. Tillägg för den här klassen kan användas för att utöka beteendet InstanceContext för eller för att lagra tillståndet för varje tjänst.

  • OperationContext – Den här klassen representerar den åtgärdsinformation som körningen samlar in för varje åtgärd. Detta inkluderar information som inkommande meddelandehuvuden, egenskaperna för inkommande meddelande, den inkommande säkerhetsidentiteten och annan information. Tillägg för den här klassen kan antingen utöka beteendet OperationContext för eller lagra tillståndet för varje åtgärd.

  • IContextChannel – Det här gränssnittet gör det möjligt att kontrollera varje tillstånd för de kanaler och proxyservrar som skapats av WCF-körningen. Tillägg för den här klassen kan antingen utöka beteendet IClientChannel för eller använda det för att lagra tillståndet för varje kanal.

I följande kodexempel visas användningen av ett enkelt tillägg för att spåra 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();
    }
  }
}

Se även