Erweiterbare ObjekteExtensible Objects

Das erweiterbare Objektmuster wird verwendet, um entweder vorhandene Laufzeitklassen um neue Funktionen zu erweitern oder um einem Objekt neue Zustandsfunktionen hinzuzufügen.The extensible object pattern is used to either extend existing runtime classes with new functionality or to add new state to an object. Erweiterungen, die einem der erweiterbaren Objekte zugeordnet sind, ermöglichen es Verhalten in verschiedenen Phasen der Verarbeitung, auf gemeinsam verwendete Zustände und Funktionen zuzugreifen, die an ein zugängliches und allgemeines erweiterbares Objekt angefügt sind.Extensions, attached to one of the extensible objects, enable behaviors at very different stages in processing to access shared state and functionality attached to a common extensible object that they can access.

Die IExtensibleObject<T > MusterThe IExtensibleObject<T> Pattern

Es gibt drei Schnittstellen im erweiterbaren Objektmuster: IExtensibleObject<T>, IExtension<T> und IExtensionCollection<T>.There are three interfaces in the extensible object pattern: IExtensibleObject<T>, IExtension<T>, and IExtensionCollection<T>.

Die IExtensibleObject<T>-Schnittstelle wird von Typen implementiert, die es IExtension<T>-Objekten ermöglichen, ihre Funktionalität anzupassen.The IExtensibleObject<T> interface is implemented by types that allow IExtension<T> objects to customize their functionality.

Erweiterbare Objekte ermöglichen die dynamische Aggregation von IExtension<T>-Objekten.Extensible objects allow dynamic aggregation of IExtension<T> objects. IExtension<T>-Objekte sind durch die folgende Schnittstelle gekennzeichnet:IExtension<T> objects are characterized by the following interface:

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

Die Typbeschränkung stellt sicher, dass Erweiterungen nur für Klassen definiert werden können, für die IExtensibleObject<T> gilt.The type restriction guarantees that extensions can only be defined for classes that are IExtensibleObject<T>. Attach und Detach führen die Benachrichtigung über eine Aggregation oder Disaggregation durch.Attach and Detach provide notification of aggregation or disaggregation.

Bei Implementierungen können Beschränkungen verwendet werden, wenn sie einem Besitzer hinzugefügt bzw. wenn sie entfernt werden.It is valid for implementations to restrict when they may be added and removed from an owner. Sie können zum Beispiel die Entfernung vollständig unmöglich machen, indem Sie das Hinzufügen oder Entfernen von Erweiterungen untersagen, wenn sich der Besitzer oder die Erweiterung in einem bestimmten Zustand befinden, das gleichzeitige Hinzufügen zu mehreren Besitzern untersagen oder nur eine einzelne Hinzufügung gefolgt von einer einzelnen Entfernung zulassen.For example, you can disallow removal entirely, disallowing adding or removing extensions when the owner or extension are in a certain state, disallow adding to multiple owners concurrently, or allow only a single addition followed by a single remove.

IExtension<T> impliziert keine Interaktionen mit anderen standardmäßigen verwalteten Schnittstellen.IExtension<T> does not imply any interactions with other standard managed interfaces. Die IDisposable.Dispose-Methode des Besitzerobjekts trennt ihre Erweiterungen in der Regel nicht ab.Specifically, the IDisposable.Dispose method on the owner object does not normally detach its extensions.

Wenn der Auflistung eine Erweiterung hinzugefügt wird, wird Attach aufgerufen, bevor die Erweiterung in die Auflistung aufgenommen wird.When an extension is added to the collection, Attach is called before it goes into the collection. Wenn eine Erweiterung aus der Auflistung entfernt wird, wird nach der Entfernung Detach aufgerufen.When an extension is removed from the collection, Detach is called after it is removed. Dies bedeutet (vorausgesetzt, es erfolgt eine entsprechende Synchronisierung), dass eine Erweiterung nur dann sicher in einer Auflistung enthalten ist, wenn sie sich zwischen den Zuständen Attach und Detach befindet.This means (assuming appropriate synchronization) an extension can count on only being found in the collection while it is between Attach and Detach.

Für das Objekt, das an FindAll oder Find übergeben wird, muss nicht IExtension<T> gelten (beispielsweise können Sie jedes Objekt übergeben), aber bei der zurückgegebenen Erweiterung handelt es sich um IExtension<T>.The object passed to FindAll or Find need not be IExtension<T> (for example, you can pass any object), but the returned extension is an IExtension<T>.

Wenn keine Erweiterung in der Auflistung ein IExtension<T>, Find gibt null zurück, und FindAll eine leere Auflistung zurück.If no extension in the collection is an IExtension<T>, Find returns null, and FindAll returns an empty collection. Wenn mehrere Erweiterungen IExtension<T> implementieren, gibt Find eine davon zurück.If multiple extensions implement IExtension<T>, Find returns one of them. Der von FindAll zurückgegebene Wert ist eine Momentaufnahme.The value returned from FindAll is a snapshot.

Es gibt zwei Hauptszenarios.There are two main scenarios. Beim ersten Szenario wird die Extensions-Eigenschaft als typbasiertes Wörterbuch verwendet, um den Zustand für ein Objekt einzufügen und auf diese Weise eine andere Komponente in die Lage zu versetzen, anhand des Typs danach zu suchen.The first scenario uses the Extensions property as a type-based dictionary to insert state on an object to enable another component to look it up using the type.

Beim zweiten Szenario werden die Eigenschaften Attach und Detach verwendet, um einem Objekt die Teilnahme am benutzerdefinierten Verhalten zu ermöglichen, zum Beispiel das Registrieren von Ereignissen, Beobachten von Zustandsübergängen usw.The second scenario uses the Attach and Detach properties to enable an object to participate in custom behavior, such as registering for events, watching state transitions, and so on.

Die IExtensionCollection<T>-Schnittstelle ist eine Auflistung von IExtension<T>-Objekten, für die der Abruf von IExtension<T> anhand des Typs zulässig ist.The IExtensionCollection<T> interface is a collection of the IExtension<T> objects that allow for retrieving the IExtension<T> by its type. IExtensionCollection<T>.Find gibt das zuletzt hinzugefügte Objekt zurück, das eine IExtension<T> dieses Typs ist.IExtensionCollection<T>.Find returns the most recently added object that is an IExtension<T> of that type.

Erweiterbare Objekte in Windows Communication FoundationExtensible Objects in Windows Communication Foundation

Es gibt vier erweiterbare Objekte in der Windows Communication Foundation (WCF):There are four extensible objects in Windows Communication Foundation (WCF):

  • ServiceHostBase – Dies ist die Basisklasse für den Host des Dienstes.ServiceHostBase – This is the base class for the service’s host. Sie können die Erweiterungen dieser Klasse verwenden, um das Verhalten von ServiceHostBase selbst zu erweitern oder um den Zustand für die Dienste einzeln zu speichern.Extensions of this class can be used to extend the behavior of the ServiceHostBase itself or to store the state for each service.

  • InstanceContext – Diese Klasse verbindet eine Instanz des Diensttyps mit der Dienstlaufzeit.InstanceContext – This class connects an instance of the service’s type with the service runtime. Sie enthält Informationen zu der Instanz sowie einen Verweis auf den InstanceContext, der ServiceHostBase enthält.It contains information about the instance as well as a reference to the InstanceContext's containing ServiceHostBase. Sie können die Erweiterungen dieser Klasse verwenden, um das Verhalten von InstanceContext zu erweitern oder um den Zustand für die Dienste einzeln zu speichern.Extensions of this class can be used to extend the behavior of the InstanceContext or to store the state for each service.

  • OperationContext – Diese Klasse stellt die Vorgangsinformationen dar, die die Laufzeit für jeden Vorgang aufzeichnet.OperationContext – This class represents the operation information that the runtime gathers for each operation. Dazu gehören auch Informationen wie Header von eingehenden Nachrichten, Eigenschaften von eingehenden Nachrichten, die eingehende Sicherheitsidentität und andere Informationen.This includes information such as the incoming message headers, the incoming message properties, the incoming security identity, and other information. Erweiterungen dieser Klasse können entweder das Verhalten des OperationContext erweitern oder den Zustand für jeden Vorgang einzeln speichern.Extensions of this class can either extend the behavior of OperationContext or store the state for each operation.

  • IContextChannel – Diese Schnittstelle ermöglicht die Untersuchung der einzelnen Zustände für die Kanäle und Proxys, die von der WCF-Laufzeit erstellt.IContextChannel – This interface allows for the inspection of each state for the channels and proxies built by the WCF runtime. Erweiterungen dieser Klasse können entweder das Verhalten des IClientChannel erweitern oder das Verhalten verwenden, um den Zustand für jeden Kanal einzeln zu speichern.Extensions of this class can either extend the behavior of IClientChannel or can use it to store the state for each channel.

-

Das folgende Codebeispiel zeigt die Verwendung einer einfachen Erweiterung zum Verfolgen von InstanceContext-Objekten.The following code example shows the use of a simple extension to track InstanceContext objects.

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

Siehe auchSee Also

IExtensibleObject<T>
IExtension<T>
IExtensionCollection<T>