Objets accessibles à distance
Les objets accessibles à distance sont des objets qui fonctionnent correctement dans un environnement largement distribué. Il existe deux types d'objets accessibles à distance :
- Les objets marshalés par valeur qui sont copiés et passés en dehors du domaine d'application.
- Les objets marshalés par référence pour lesquels un proxy est créé et utilisé par le client pour accéder à l'objet à distance.
Objets marshalés par valeur
Les objets marshalés par valeur (MBV, Marshal-By-Value) déclarent leurs règles de sérialisation (soit en implémentant ISerializable pour implémenter leur propre sérialisation, soit en étant décorés à l'aide de SerializableAttribute, ce qui indique au système de sérialiser l'objet automatiquement) mais n'étendent pas MarshalByRefObject. Le système d'accès distant effectue une copie complète de ces objets et passe celle-ci au domaine d'application appelant. Une fois que la copie se trouve dans le domaine d'application de l'appelant, les appels destinés à la copie sont acheminés directement à cette copie. En outre, des objets marshalés par valeur passés en tant qu'argument le sont également par valeur. À part déclarer l'attribut SerializableAttribute ou implémenter ISerializable, vous n'avez pas besoin de faire quoique ce soit pour passer des instances de votre classe par valeur au-delà des limites de contexte ou d'application.
Remarque À partir de la version 1.1 du .NET Framework, l'infrastructure de l'accès distant ne désérialise pas automatiquement certains types sur le serveur. Si cela est vrai pour votre scénario, vous devez définir le niveau de désérialisation du serveur à Full avant que le serveur ne soit en mesure de désérialiser et d'utiliser votre objet marshalé par valeur. Pour plus d'informations, consultez Désérialisation automatique dans .NET Remoting.
Utilisez des objets marshalés par valeur lorsque, pour des raisons de performance ou de traitement, vous êtes amené à transférer l'état de l'objet et toute fonctionnalité exécutable vers le domaine d'application cible. Dans de nombreux scénarios, cette opération réduit les longs accès répétés, consommateurs de ressources sur le réseau, entre processus et au-delà des limites des domaines d'application. Les objets marshalés par valeur sont également utilisés directement à partir du domaine d'application d'origine de l'objet. Dans ce cas, en l'absence de tout marshaling, aucune copie n'est effectuée et l'accès est très efficace.
D'un autre côté, si vos objets publiés sont très gros, le passage d'une copie complète sur un réseau occupé n'est peut-être pas le meilleur choix pour votre application. En outre, aucun changement apporté à l'état de l'objet copié n'est jamais retransmis à l'objet d'origine dans le domaine d'application initial. À un niveau abstrait, ce scénario est similaire à celui de la demande d'une page HTML statique effectuée par un navigateur client. Le serveur copie le fichier, l'écrit dans un flux, l'envoie et ne s'en occupe plus. Toute demande ultérieure représente ni plus ni moins qu'une autre demande d'une autre copie.
Le système d'accès distant utilise les objets sérialisables de façon extensive. Une référence vers un objet dans un autre domaine d'application, représentée dans le système d'accès distant par la classe ObjRef, est elle-même sérialisable ; il doit être possible de la copier exactement et d'envoyer la copie à une demande. Les objets de message implémentent IMessage, car ils sont les conteneurs génériques des informations d'appel et de toute autre référence d'objet nécessaire. En outre, des objets qui transfèrent simplement des données sont souvent des objets sérialisables. DataSet, par exemple, étend MarshalByValueComponent qui implémente ISerializable.
Utilisation d'exceptions d'accès distant définies par l'utilisateur
Les exceptions définies par le système sont toutes de type marshalé par valeur (elles implémentent l'interface ISerializable) ; lorsqu'elles sont levées par un objet distant, elles sont automatiquement copiées vers l'appelant, si les configurations d'accès distant le permettent. (À partir de la version 1.1 du .NET Framework, l'élément <customErrors> doit avoir la valeur off pour permettre aux exceptions d'être transmises à l'appelant.)
Pour créer vos propres types d'exceptions pouvant être levées par des objets distants et interceptées par des appelants distants, vous devez procéder comme suit :
- Implémentez ISerializable.
- Placez l'attribut SerializableAttribute sur la classe.
- Implémentez un constructeur de désérialisation qui prend des objets SerializationInfo et StreamingContext comme paramètres.
L'exemple de code C# suivant illustre une implémentation simple qui, si elle est correctement configurée, est de nouveau copiée vers l'appelant lorsqu'elle est levée par l'objet serveur distant.
[Serializable]
public class CustomRemotableException : RemotingException, ISerializable {
private string _internalMessage;
public CustomRemotableException(){
_internalMessage = String.Empty;
}
public CustomRemotableException(string message){
_internalMessage = message;
}
public CustomRemotableException(SerializationInfo info, StreamingContext context){
_internalMessage = (string)info.GetValue("_internalMessage", typeof(string));
}
public override void GetObjectData(SerializationInfo info, StreamingContext context){
info.AddValue("_internalMessage", _internalMessage);
}
// Returns the exception information.
public override string Message{
get {
return "This is your custom remotable exception returning: \""
+ _internalMessage
+ "\"";
}
}
}
Objets marshalés par référence
Les objets marshalés par référence (MBR, Marshal-By-Reference) sont des objets accessibles à distance qui étendent au moins System.MarshalByRefObject. En fonction du type d'activation déclaré, lorsqu'un client crée une instance d'un objet marshalé par référence dans son propre domaine d'application, l'infrastructure .NET Remoting crée un objet proxy dans le domaine d'application de l'appelant qui représente l'objet marshalé par référence et retourne une référence vers ce proxy à l'appelant. Le client effectue ensuite des appels sur le proxy. L'accès distant marshale ces appels, les renvoie au domaine d'application d'origine et effectue l'appel sur l'objet réel.
Remarque Si le client se trouve dans le même domaine d'application que l'objet marshalé par référence, l'infrastructure retourne au client une référence directe à l'objet marshalé par référence ce qui évite la charge du marshaling.
Si MarshalByRefObject est passé en tant que paramètre, il devient un proxy dans l'autre domaine d'application lorsque l'appel parvient. Les valeurs de retour marshalées par référence et les paramètres out fonctionnent de la même manière.
Remarque À partir de la version 1.1 du .NET Framework, l'infrastructure de l'accès distant ne désérialise pas automatiquement certains types sur le serveur. Par exemple, pour obtenir une prise en charge des objets marshalés par référence passés en tant que paramètres, vous devez définir le niveau de désérialisation du serveur à Full avant que le serveur ne soit en mesure de désérialiser et d'utiliser le paramètre marshalé par référence. Pour plus d'informations sur ce scénario ainsi que sur d'autres, consultez Désérialisation automatique dans .NET Remoting.
Vous devez utiliser des objets marshalés par référence lorsque l'état de l'objet et toute fonctionnalité exécutable doivent rester dans le domaine d'application dans lequel il a été créé. Par exemple, un objet possédant un champ interne qui est un handle de système d'exploitation doit étendre MarshalByRefObject, car le handle de système d'exploitation n'aurait aucun sens dans un autre domaine d'application, dans un autre processus ou sur un autre ordinateur. Parfois la taille d'un objet peut être également trop large ; ce qui vaut pour un serveur robuste ne convient pas forcément lors de l'envoi sur un réseau à un modem d'un débit de 33,6 Kbits/s.
Objets liés au contexte
Les objets liés au contexte sont des objets marshalés par référence qui héritent de System.ContextBoundObject, qui hérite lui-même de System.MarshalByRefObject. Vous pouvez vous représenter un contexte sous la forme d'une sous-division d'un domaine d'application, qui fournit un environnement riche aux objets qui y résident lors de l'exécution. Par exemple, un contexte peut garantir que les objets ne seront pas accessibles simultanément par plusieurs threads. Chaque domaine d'application possède un contexte par défaut. La plupart du code managé crée des objets et appelle des membres directement à partir du même domaine d'application à l'aide du contexte par défaut de ce domaine, sans problème lié au contexte. Tous les types qui héritent de ContextBoundObject sont exposés sous forme de proxies à d'autres contextes (dans le même domaine ou dans d'autres domaines).
Par exemple, supposons que vous ayez une méthode sur un type qui fait partie d'une transaction et qui par conséquent obéit aux règles spécifiques au contexte dans lequel il a été créé. Ce type doit hériter de ContextBoundObject de façon à ce que l'objet soit accessible à partir de son propre contexte et que le système puisse appliquer les règles relatives aux transactions associées à cet objet et à ses méthodes. Si ContextBoundObject est appelé à partir d'un autre contexte au sein du même domaine d'application, un proxy est créé pour l'appelant, mais la communication intercontexte ne passe pas par le système de canal, ce qui augmente l'efficacité de l'appel dans cette situation.
Étant donné que le franchissement des limites consomme du temps processeur, il vous faut déterminer quelles limites vos objets doivent franchir avant de décider quel type d'objet accessible à distance correspond à votre serveur. Des objets spécifiques à un contexte particulier ne peuvent être accessibles directement qu'à partir de ce contexte. Cela s'applique également aux objets spécifiques à un domaine d'application particulier. Pour appeler à distance l'un ou l'autre objet, le système distant doit réussir à franchir une limite de contexte, une limite d'application ou les deux, avant d'appeler l'objet serveur à partir de la limite qui lui est spécifique. Si vous n'avez pas besoin de vérifier le contexte pour appeler votre objet, il n'est pas nécessaire que votre type distant étende ContextBoundObject ; MarshalByRefObject fonctionnera mieux. Si vous avez besoin de vérifier le contexte, vous devez étendre ContextBoundObject, mais vous devez comprendre que la limite supplémentaire doit être franchie avant que l'appel soit effectué sur votre objet.
Voir aussi
Objets accessibles à distance et objets non accessibles à distance | ContextBoundObject | Objets non accessibles à distance