Erweitern von Verteilern
Verteiler sind dafür verantwortlich, eingehende Nachrichten aus den zugrunde liegenden Kanälen abzufangen, sie in Methodenaufrufe im Anwendungscode zu übersetzen und die Ergebnisse zurück an den Aufrufer zu senden. Verteilererweiterungen versetzen Sie in die Lage, diese Verarbeitung zu ändern. Sie können Nachrichten- oder Parameterinspektoren implementieren, die den Inhalt von Nachrichten oder Parametern überprüfen bzw. ändern. Sie können die Weiterleitung von Nachrichten an Vorgänge ändern oder andere Funktionalität bereitstellen.
In diesem Thema wird beschrieben, wie die DispatchRuntime-Klasse und die DispatchOperation-Klasse in einer Windows Communication Foundation (WCF)-Dienstanwendung verwendet werden, um das Standardausführungsverhalten eines Verteilers zu ändern oder um Nachrichten, Parameter oder Rückgabewerte abzufangen oder zu ändern, bevor oder nachdem sie aus der Kanalschicht gesendet oder abgerufen werden. Weitere Informationen über die entsprechende Nachrichtenverarbeitung zur Clientlaufzeit finden Sie unter Erweitern von Clients. Informationen zum Verständnis der Rolle, die IExtensibleObject-Typen beim Zugriff auf gemeinsam verwendete Zustände zwischen verschiedenen Laufzeitanpassungsobjekten spielen, finden Sie unter Erweiterbare Objekte.
Verteiler
Die Dienstmodellebene führt die Konvertierung zwischen dem Programmiermodell des Entwicklers und dem zugrunde liegenden Nachrichtenaustausch, gewöhnlich als Kanalschicht bezeichnet, durch. In WCF sind die Kanal- und die Endpunktverteiler (ChannelDispatcher bzw. EndpointDispatcher) die Dienstkomponenten, die dafür verantwortlich sind, neue Kanäle zu akzeptieren, Nachrichten zu empfangen, Vorgänge zu verteilen und aufzurufen sowie Antworten zu verarbeiten. Verteilerobjekte sind empfangende Objekte, aber auch Rückrufvertragsimplementierungen in Duplexdiensten machen ihre Verteilerobjekte für Überprüfung, Änderung oder Erweiterung verfügbar.
Der Kanalverteiler (und der zugehörige IChannelListener) fangen eingehende Nachrichten aus den zugrunde liegenden Kanälen ab und übergeben diese Nachrichten ihren jeweiligen Endpunktverteilern. Jeder Endpunktverteiler hat eine DispatchRuntime, die die Nachrichten an die entsprechende DispatchOperation weiterleitet, die für den Aufruf der Methode verantwortlich ist, die den Vorgang implementiert. Dabei werden verschiedene optionale und notwendige Erweiterungsklassen aufgerufen. In diesem Thema wird erklärt, wie diese Elemente zusammenpassen, und wie Sie deren Eigenschaften ändern und eigenen Code schreiben, um die Basisfunktionalität zu erweitern.
Verteilereigenschaften und geänderte Anpassungsobjekte werden mithilfe von Dienst-, Endpunkt-, Vertrags- und Vorgangsverhaltensobjekten eingefügt. In diesem Thema wird nicht beschrieben, wie Verhaltensobjekte verwendet werden. Weitere Informationen zu den Typen, die verwendet werden, um Verteileränderungen einzufügen, finden Sie unter Konfigurieren und Erweitern der Laufzeit mit Verhalten.
Die folgende Grafik bietet einen Überblick über die architektonischen Elemente in einem Dienst.
Kanalverteiler
Ein ChannelDispatcher-Objekt wird erstellt, um einen IChannelListener an einem bestimmten URI (als Abhör-URI bezeichnet) einer Instanz eines Diensts zuzuordnen. Jedes ServiceHost-Objekt kann über viele ChannelDispatcher-Objekte verfügen, die jeweils einem Listener und einem Abhör-URI zugeordnet sind. Wenn eine Nachricht eingeht, fragt der ChannelDispatcher jedes der zugeordneten EndpointDispatcher-Objekte ab, ob der Endpunkt die Nachricht akzeptieren kann, und leitet die Nachricht an den Endpunkt weiter, der dies kann.
Alle Eigenschaften, die die Lebensdauer und das Verhalten einer Kanalsitzung steuern, sind zur Überprüfung oder Änderung im ChannelDispatcher-Objekt verfügbar. Dies schließt benutzerdefinierte Kanalinitialisierer, den Kanallistener, den Host, den zugeordneten InstanceContext usw. ein.
Endpunktverteiler
Das EndpointDispatcher-Objekt ist verantwortlich für das Verarbeiten von Nachrichten von einem ChannelDispatcher, wenn die Zieladresse einer Nachricht mit der AddressFilter-Eigenschaft übereinstimmt und die Nachrichtenaktion mit der ContractFilter-Eigenschaft übereinstimmt. Wenn zwei EndpointDispatcher-Objekte eine Nachricht akzeptieren können, bestimmt der Wert der FilterPriority-Eigenschaft den Endpunkt mit höherer Priorität.
Verwenden Sie das EndpointDispatcher-Objekt, um die beiden Haupterweiterungspunkte des Dienstmodells – die DispatchRuntime-Klasse und die DispatchOperation-Klasse – abzurufen, die Sie verwenden können, um die Verarbeitung durch den Verteiler anzupassen. Die DispatchRuntime-Klasse ermöglicht Benutzern, den Verteiler im Vertragsbereich (also für alle Nachrichten in einem Vertrag) abzufangen und zu erweitern. Die DispatchOperation-Klasse ermöglicht Benutzern, den Verteiler im Vorgangsbereich (also für alle Nachrichten in einem Vorgang) abzufangen und zu erweitern.
Szenarien
Es gibt eine Reihe von Gründen, den Verteiler zu erweitern:
Benutzerdefinierte Nachrichtenvalidierung. Benutzer können durchsetzen, dass eine Nachricht für ein bestimmtes Schema gültig ist. Dies kann über die Implementierung der Nachrichteninterceptorschnittstellen erreicht werden. Ein Beispiel finden Sie unter Nachrichteninspektoren.
Benutzerdefinierte Nachrichtenprotokollierung. Benutzer können einige Anwendungsnachrichten prüfen und protokollieren, die durch einen Endpunkt fließen. Dies kann ebenfalls mit den Nachrichteninterceptorschnittstellen erreicht werden.
Benutzerdefinierte Nachrichtentransformationen. Benutzer können bestimmte Transformationen (beispielsweise die Versionsverwaltung) auf die Nachricht in der Laufzeit anwenden. Auch dies kann mit den Nachrichteninterceptorschnittstellen erreicht werden.
Benutzerdefiniertes Datenmodell. Benutzer können ein anderes Datenserialisierungsmodell verwenden als die standardmäßig in WCF unterstützten (nämlich System.Runtime.Serialization.DataContractSerializer, System.Xml.Serialization.XmlSerializer und unformatierte Nachrichten). Dies kann über die Implementierung der Nachrichtenformatierungsschnittstellen erreicht werden. Ein Beispiel finden Sie unter Vorgangsformatierer und Vorgangsauswahl.
Benutzerdefinierte Parametervalidierung. Benutzer können durchsetzen, dass typisierte Parameter gültig sind (im Gegensatz zu XML). Dies kann mit den Parameterinspektorschnittstellen erreicht werden. Ein Beispiel finden Sie unter Parameter Filter.
Benutzerdefinierte Vorgangsverteilung. Benutzer können die Verteilung an etwas anderes als an eine Aktion implementieren – beispielsweise an das Textelement oder an eine benutzerdefinierte Nachrichteneigenschaft. Dies kann über die Verwendung der IDispatchOperationSelector-Schnittstelle erreicht werden. Ein Beispiel finden Sie unter Vorgangsformatierer und Vorgangsauswahl.
Objektpooling. Benutzer können Instanzen zusammenlegen, statt für jeden Aufruf eine neue Instanz zuzuordnen. Dies kann über die Implementierung der Instanzanbieterschnittstellen erreicht werden. Ein Beispiel finden Sie unter Pooling.
Instanzleasing. Benutzer können ein Leasingmuster ähnlich dem von .NET Framework Remoting für die Lebensdauer der Instanz implementieren. Dies kann mit den Instanzkontextlebensdauer-Schnittstellen erreicht werden.
Benutzerdefinierte Fehlerbehandlung. Benutzer können steuern, wie lokale Fehler verarbeitet werden und wie Clients über Fehler unterrichtet werden. Dies kann mithilfe der IErrorHandler-Schnittstellen implementiert werden.
Benutzerdefiniertes Autorisierungsverhalten Benutzer können eine benutzerdefinierte Zugriffssteuerung implementieren, indem sie die Vertrags- und Vorgangslaufzeitelemente erweitern und auf in der Nachricht enthaltenen Tokens basierende Sicherheitsüberprüfungen hinzufügen. Dies kann entweder mit den Nachrichteninterceptor- oder den Parameterinterceptorschnittstellen erreicht werden. Beispiele dafür finden Sie unter Security Extensibility Samples.
Vorsicht: Da das Ändern der Sicherheitseigenschaften potentiell die Sicherheit von WCF-Anwendungen gefährden kann, wird dringend empfohlen, sicherheitsbezogene Änderungen mit Sorgfalt auszuführen und sie vor der Bereitstellung umfassend zu testen. Benutzerdefinierte WCF-Laufzeitvalidierungs-Steuerelemente. Sie können benutzerdefinierte Laufzeitvalidierungs-Steuerelemente installieren, die Dienste, Verträge und Bindungen überprüfen, um in Bezug auf WCF-Anwendungen Sicherheitsrichtlinien auf Unternehmensebene durchzusetzen. (Ein Beispiel finden Sie unter Vorgehensweise: Endpunkte im Unternehmen sperren.)
Verwenden der DispatchRuntime-Klasse
Verwenden Sie die DispatchRuntime-Klasse, um entweder das Standardverhalten eines Diensts oder eines einzelnen Endpunkts zu ändern, oder um Objekte einzufügen, die benutzerdefinierte Änderungen für einen oder für beide der folgenden Dienstprozesse implementieren (oder für Clientprozesse im Fall eines Duplexclients):
Die Transformation eingehender Nachrichten in Objekte und die Freigabe dieser Objekte als Methodenaufrufe in einem Dienstobjekt.
Die Transformation von Objekten, die von der Antwort auf einen Dienstvorgangsaufruf empfangen wurden, in ausgehende Nachrichten.
Die DispatchRuntime-Klasse ermöglicht Ihnen, den Kanal- oder Endpunktverteiler für alle Nachrichten in einem bestimmten Vertrag auch dann abzufangen und zu erweitern, wenn eine Nachricht nicht erkannt wurde. Wenn eine Nachricht eintrifft, die mit keinem im Vertrag deklarierten Vorgang übereinstimmt, wird sie an den Vorgang geleitet, der von der UnhandledDispatchOperation-Eigenschaft zurückgegeben wird. Informationen dazu, wie ein Verteiler erweitert wird, der alle Nachrichten für einen bestimmten Vorgang abfängt, finden Sie unter der DispatchOperation-Klasse.
Es gibt vier Hauptbereiche der Verteilererweiterbarkeit, die von der DispatchRuntime-Klasse verfügbar gemacht werden:
Kanalkomponenten verwenden Eigenschaften der DispatchRuntime-Klasse sowie jene des zugeordneten Kanalverteilers, der von der ChannelDispatcher-Eigenschaft zurückgegeben wird, um festzulegen, wie der Kanalverteiler Kanäle akzeptiert und schließt. Dazu gehören die Eigenschaften ChannelInitializers und InputSessionShutdownHandlers.
Nachrichtenkomponenten werden für jede verarbeitete Nachricht angepasst. Dazu gehören die Eigenschaften MessageInspectors, OperationSelector, Operations und ErrorHandlers.
Instanzkomponenten passen die Erstellung, Lebensdauer und Freigabe von Instanzen des Diensttyps an. Weitere Informationen zur Lebensdauer von Dienstobjekten finden Sie in den Ausführungen zur InstanceContextMode-Eigenschaft. Dazu gehören die Eigenschaften InstanceContextInitializers und InstanceProvider.
Sicherheitsrelevante Komponenten können die folgenden Eigenschaften verwenden:
SecurityAuditLogLocation gibt an, wohin Überwachungsereignisse geschrieben werden.
ImpersonateCallerForAllOperations steuert, ob der Dienst versucht, mithilfe der Anmeldeinformationen der eingehenden Nachricht einen Identitätswechsel durchzuführen.
MessageAuthenticationAuditLevel steuert, ob Ereignisse für erfolgreiche Nachrichtenauthentifizierung in das Ereignisprotokoll geschrieben werden, das von SecurityAuditLogLocation angegeben wird.
PrincipalPermissionMode steuert, wie die CurrentPrincipal-Eigenschaft festgelegt wird.
ServiceAuthorizationAuditLevel gibt an, wie die Überwachung von Autorisierungsereignissen durchgeführt wird.
SuppressAuditFailure gibt an, ob während des Protokollierungsprozesses auftretende nicht schwerwiegende Ausnahmen unterdrückt werden sollen.
In der Regel werden benutzerdefinierte Erweiterungsobjekte einer DispatchRuntime-Eigenschaft zugewiesen oder durch ein Dienstverhalten (ein Objekt, das IServiceBehavior implementiert), durch ein Vertragsverhalten (ein Objekt, das IContractBehavior implementiert) oder durch ein Endpunktverhalten (ein Objekt, das IEndpointBehavior implementiert) in eine Auflistung eingefügt. Das installierende Verhaltensobjekt wird dann der entsprechenden Verhaltensauflistung entweder programmgesteuert oder durch Implementierung eines benutzerdefinierten BehaviorExtensionElement-Objekts hinzugefügt, um das Verhalten, das eingefügt werden soll, mithilfe einer Anwendungskonfigurationsdatei zu aktivieren.
Duplexclients (Clients, die den durch einen Duplexdienst angegebenen Rückrufvertrag implementieren) verfügen auch über ein DispatchRuntime-Objekt, auf das mithilfe der CallbackDispatchRuntime-Eigenschaft zugegriffen werden kann.
Verwenden der DispatchOperation-Klasse
Die DispatchOperation-Klasse ist der Speicherort für Laufzeitänderungen und die Einfügemarke für benutzerdefinierte Erweiterungen, die nur auf einen Dienstvorgang abzielen. (Um das Dienstlaufzeit-Verhalten für alle Nachrichten in einem Vertrag zu ändern, verwenden Sie die DispatchRuntime-Klasse.)
Installieren Sie DispatchOperation-Änderungen mithilfe eines benutzerdefinierten Dienstverhaltensobjekts.
Verwenden Sie die Operations-Eigenschaft, um das DispatchOperation-Objekt zu suchen, das einen bestimmten Dienstvorgang darstellt.
Die folgenden Eigenschaften kontrollieren die Laufzeitausführung auf Vorgangsebene:
Die Eigenschaften Action, ReplyAction, FaultContractInfos, IsOneWay, IsTerminating und Name erhalten die jeweiligen Werte für den Vorgang.
Die Eigenschaften TransactionAutoComplete und TransactionRequired geben das Transaktionsverhalten an.
Die Eigenschaften ReleaseInstanceBeforeCall und ReleaseInstanceAfterCall steuern die Lebensdauer des benutzerdefinierten Dienstobjekts bezogen auf den InstanceContext.
Die Eigenschaften DeserializeRequest, SerializeReply und Formatter ermöglichen die explizite Steuerung der Konvertierung von Nachrichten in Objekte und von Objekten in Nachrichten.
Die Impersonation-Eigenschaft gibt die Ebene des Identitätswechsels des Vorgangs an.
Die CallContextInitializers-Eigenschaft fügt benutzerdefinierte Erweiterungen des Aufrufkontexts für den Vorgang ein.
Die AutoDisposeParameters-Eigenschaft steuert, wann Parameterobjekte gelöscht werden.
Die Invoker-Eigenschaft ist für das Einfügen eines benutzerdefinierten aufrufenden Objekts.
Die ParameterInspectors-Eigenschaft ermöglicht es Ihnen, einen benutzerdefinierten Parameterinspektor einzufügen, den Sie verwenden können, um Parameter und Rückgabewerte zu überprüfen oder zu ändern.
Siehe auch
Aufgaben
Vorgehensweise: Überprüfen und Ändern von Nachrichten auf dem Dienst
Vorgehensweise: Überprüfen oder Ändern von Parametern
Vorgehensweise: Endpunkte im Unternehmen sperren