Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Le modèle d’objet extensible est utilisé pour étendre des classes runtime existantes avec de nouvelles fonctionnalités ou pour ajouter un nouvel état à un objet. Les extensions, attachées à l’un des objets extensibles, permettent des comportements à des étapes très différentes du traitement pour accéder à l’état partagé et aux fonctionnalités attachées à un objet extensible commun auquel ils peuvent accéder.
Le modèle IExtensibleObject<T>
Il existe trois interfaces dans le modèle d’objet extensible : IExtensibleObject<T>, IExtension<T>et IExtensionCollection<T>.
L’interface IExtensibleObject<T> est implémentée par des types qui permettent IExtension<T> aux objets de personnaliser leurs fonctionnalités.
Les objets extensibles permettent l’agrégation dynamique d’objets IExtension<T> . IExtension<T> les objets sont caractérisés par l’interface suivante :
public interface IExtension<T>
where T : IExtensibleObject<T>
{
void Attach(T owner);
void Detach(T owner);
}
La restriction de type garantit que les extensions ne peuvent être définies que pour les classes qui sont IExtensibleObject<T>. Attach et Detach fournissent des notifications d’agrégation ou de désagrégation.
Il est légitime que les implémentations restreignent les moments où elles peuvent être ajoutées et retirées d'un propriétaire. Par exemple, vous pouvez interdire entièrement la suppression, interdire l’ajout ou la suppression d’extensions lorsque le propriétaire ou l’extension se trouvent dans un certain état, interdire l’ajout à plusieurs propriétaires simultanément ou autoriser uniquement un seul ajout suivi d’une seule suppression.
IExtension<T> n’implique aucune interaction avec d’autres interfaces managées standard. Plus précisément, la IDisposable.Dispose méthode sur l’objet propriétaire ne détache pas normalement ses extensions.
Lorsqu'une extension est ajoutée à la collection, la fonction Attach est appelée avant d'être placée dans la collection. Lorsqu'une extension est supprimée de la collection, l'appel Detach a lieu après sa suppression. Cela signifie (en supposant que la synchronisation soit appropriée) qu'une extension ne peut compter que sur le fait d'être trouvée dans la collection tant qu'elle se situe entre Attach et Detach.
L’objet passé à FindAll ou Find n’a pas besoin d’être IExtension<T> (par exemple, vous pouvez passer n’importe quel objet), mais l’extension retournée est un IExtension<T>.
Si aucune extension de la collection n’est un IExtension<T>, Find retourne null et FindAll retourne une collection vide. Si plusieurs extensions implémentent IExtension<T>, Find retourne l’une d’elles. La valeur retournée par FindAll est un instantané.
Il existe deux scénarios principaux. Le premier scénario utilise la Extensions propriété comme dictionnaire basé sur un type pour insérer l’état sur un objet pour permettre à un autre composant de le rechercher à l’aide du type.
Le deuxième scénario utilise les propriétés Attach et Detach pour permettre à un objet de participer à un comportement personnalisé, comme l'enregistrement à des événements, la surveillance des transitions d’état, etc.
L’interface IExtensionCollection<T> est une collection d’objets IExtension<T> qui permettent de récupérer le IExtension<T> par type. IExtensionCollection<T>.Find retourne l’objet ajouté le plus récemment qui est un IExtension<T> de ce type.
Objets extensibles dans Windows Communication Foundation
Il existe quatre objets extensibles dans Windows Communication Foundation (WCF) :
ServiceHostBase : il s’agit de la classe de base de l’hôte du service. Les extensions de cette classe peuvent être utilisées pour étendre le comportement du ServiceHostBase lui-même ou pour stocker l’état de chaque service.
InstanceContext : cette classe connecte une instance du type du service avec le runtime de service. Il contient des informations sur l’instance ainsi qu’une référence à l’élément InstanceContext contenant ServiceHostBase. Les extensions de cette classe peuvent être utilisées pour étendre le comportement du InstanceContext ou pour stocker l’état de chaque service.
OperationContext : cette classe représente les informations d’opération collectées par le runtime pour chaque opération. Cela inclut des informations telles que les en-têtes de message entrants, les propriétés du message entrant, l’identité de sécurité entrante et d’autres informations. Les extensions de cette classe peuvent soit étendre le comportement de OperationContext, soit stocker l’état pour chaque opération.
IContextChannel : cette interface permet l’inspection de chaque état pour les canaux et proxys générés par le runtime WCF. Les extensions de cette classe peuvent soit étendre le comportement de IClientChannel, soit l'utiliser pour stocker l'état de chaque canal.
L’exemple de code suivant montre l’utilisation d’une extension simple pour suivre les InstanceContext objets.
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
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()
{ _instanceId = Guid.NewGuid().ToString(); }
public string InstanceId => _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();
}
}
}