Notes
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.
L’exemple DataContract montre comment les processus tels que la sérialisation, la désérialisation, l’exportation de schéma et l’importation de schéma peuvent être personnalisés à l’aide d’une classe de substitution de contrat de données. Cet exemple montre comment utiliser un substitut dans un scénario client et serveur où les données sont sérialisées et transmises entre un client et un service Windows Communication Foundation (WCF).
Remarque
La procédure d’installation et les instructions de génération de cet exemple se trouvent à la fin de cette rubrique.
L’exemple utilise le contrat de service suivant :
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[AllowNonSerializableTypes]
public interface IPersonnelDataService
{
[OperationContract]
void AddEmployee(Employee employee);
[OperationContract]
Employee GetEmployee(string name);
}
L’opération AddEmployee
permet aux utilisateurs d’ajouter des données sur les nouveaux employés et l’opération GetEmployee
prend en charge la recherche d’employés en fonction du nom.
Ces opérations utilisent le type de données suivant :
[DataContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
class Employee
{
[DataMember]
public DateTime dateHired;
[DataMember]
public Decimal salary;
[DataMember]
public Person person;
}
Dans le Employee
, la classe Person
(illustrée dans l'exemple de code suivant) ne peut pas être sérialisée par le DataContractSerializer, car elle n'est pas une classe de contrat de données valide.
public class Person
{
public string firstName;
public string lastName;
public int age;
public Person() { }
}
Vous pouvez appliquer l’attribut DataContractAttribute à la Person
classe, mais cela n’est pas toujours possible. Par exemple, la Person
classe peut être définie dans un assembly distinct sur lequel vous n’avez aucun contrôle.
Étant donné cette restriction, une façon de sérialiser la classe Person
consiste à la remplacer par une autre classe marquée avec DataContractAttribute et à copier les données nécessaires dans la nouvelle classe. L’objectif est de faire apparaître la Person
classe en tant que DataContract à l’objet DataContractSerializer. Notez que voici une manière de sérialiser des classes qui ne sont pas des contrats de données.
L’exemple remplace logiquement la Person
classe par une autre classe nommée PersonSurrogated
.
[DataContract(Name="Person", Namespace = "http://Microsoft.ServiceModel.Samples")]
public class PersonSurrogated
{
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
[DataMember]
public int Age;
}
Le substitut de contrat de données est utilisé pour effectuer ce remplacement. Un substitut de contrat de données est une classe qui implémente IDataContractSurrogate. Dans cet exemple, la AllowNonSerializableTypesSurrogate
classe implémente cette interface.
Dans l’implémentation de l’interface, la première tâche consiste à établir un mappage de type à partir de Person
vers PersonSurrogated
. Cela est utilisé à la fois au moment de la sérialisation ainsi qu’au moment de l’exportation de schéma. Ce mappage est obtenu en implémentant la GetDataContractType(Type) méthode.
public Type GetDataContractType(Type type)
{
if (typeof(Person).IsAssignableFrom(type))
{
return typeof(PersonSurrogated);
}
return type;
}
La GetObjectToSerialize(Object, Type) méthode mappe une Person
instance à une PersonSurrogated
instance pendant la sérialisation, comme illustré dans l’exemple de code suivant.
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj is Person)
{
Person person = (Person)obj;
PersonSurrogated personSurrogated = new PersonSurrogated();
personSurrogated.FirstName = person.firstName;
personSurrogated.LastName = person.lastName;
personSurrogated.Age = person.age;
return personSurrogated;
}
return obj;
}
La GetDeserializedObject(Object, Type) méthode fournit le mappage inverse pour la désérialisation, comme indiqué dans l’exemple de code suivant.
public object GetDeserializedObject(object obj,
Type targetType)
{
if (obj is PersonSurrogated)
{
PersonSurrogated personSurrogated = (PersonSurrogated)obj;
Person person = new Person();
person.firstName = personSurrogated.FirstName;
person.lastName = personSurrogated.LastName;
person.age = personSurrogated.Age;
return person;
}
return obj;
}
Pour mapper le PersonSurrogated
contrat de données à la classe existante Person
pendant l’importation de schéma, l’exemple implémente la GetReferencedTypeOnImport(String, String, Object) méthode, comme indiqué dans l’exemple de code suivant.
public Type GetReferencedTypeOnImport(string typeName,
string typeNamespace, object customData)
{
if (
typeNamespace.Equals("http://schemas.datacontract.org/2004/07/DCSurrogateSample")
)
{
if (typeName.Equals("PersonSurrogated"))
{
return typeof(Person);
}
}
return null;
}
L’exemple de code suivant termine l’implémentation de l’interface IDataContractSurrogate .
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(
System.CodeDom.CodeTypeDeclaration typeDeclaration,
System.CodeDom.CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
public object GetCustomDataToExport(Type clrType,
Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(
System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public void GetKnownCustomDataTypes(
KnownTypeCollection customDataTypes)
{
// It does not matter what we do here.
throw new NotImplementedException();
}
Dans cet exemple, la substitution est activée dans ServiceModel par un attribut appelé AllowNonSerializableTypesAttribute
. Les développeurs doivent appliquer cet attribut sur leur contrat de service, comme indiqué sur le IPersonnelDataService
contrat de service ci-dessus. Cet attribut implémente IContractBehavior
et définit le substitut sur les opérations dans les méthodes ApplyClientBehavior
et ApplyDispatchBehavior
.
L’attribut n’est pas nécessaire dans ce cas - il est utilisé à des fins de démonstration dans cet exemple. Les utilisateurs peuvent également activer un substitut en ajoutant manuellement un code similaire IContractBehavior
, IEndpointBehavior
ou IOperationBehavior
en utilisant du code ou une configuration.
L’implémentation IContractBehavior
recherche des opérations qui utilisent DataContract en vérifiant si elles ont un DataContractSerializerOperationBehavior
enregistré. Si c'est le cas, cela applique la propriété DataContractSurrogate
à ce comportement. L’exemple de code suivant montre comment procéder. La définition du substitut sur ce comportement d’opération permet pour ce dernier une sérialisation et une désérialisation.
public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime proxy)
{
foreach (OperationDescription opDesc in description.Operations)
{
ApplyDataContractSurrogate(opDesc);
}
}
public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatch)
{
foreach (OperationDescription opDesc in description.Operations)
{
ApplyDataContractSurrogate(opDesc);
}
}
private static void ApplyDataContractSurrogate(OperationDescription description)
{
DataContractSerializerOperationBehavior dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsOperationBehavior != null)
{
if (dcsOperationBehavior.DataContractSurrogate == null)
dcsOperationBehavior.DataContractSurrogate = new AllowNonSerializableTypesSurrogate();
}
}
D'autres étapes doivent être effectuées pour brancher le substitut afin de pouvoir être utilisé lors de la génération des métadonnées. Un mécanisme pour ce faire consiste à fournir un IWsdlExportExtension
, illustré par cet exemple. Une autre façon est de modifier directement WsdlExporter
.
L’attribut AllowNonSerializableTypesAttribute
implémente IWsdlExportExtension
et IContractBehavior
. L’extension peut être une IContractBehavior
ou IEndpointBehavior
dans ce cas. Son implémentation de la méthode IWsdlExportExtension.ExportContract
active le substitut en l'ajoutant au XsdDataContractExporter
utilisé lors de la génération des schémas du DataContract. L’extrait de code suivant montre comment procéder.
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
if (exporter == null)
throw new ArgumentNullException("exporter");
object dataContractExporter;
XsdDataContractExporter xsdDCExporter;
if (!exporter.State.TryGetValue(typeof(XsdDataContractExporter), out dataContractExporter))
{
xsdDCExporter = new XsdDataContractExporter(exporter.GeneratedXmlSchemas);
exporter.State.Add(typeof(XsdDataContractExporter), xsdDCExporter);
}
else
{
xsdDCExporter = (XsdDataContractExporter)dataContractExporter;
}
if (xsdDCExporter.Options == null)
xsdDCExporter.Options = new ExportOptions();
if (xsdDCExporter.Options.DataContractSurrogate == null)
xsdDCExporter.Options.DataContractSurrogate = new AllowNonSerializableTypesSurrogate();
}
Lorsque vous exécutez l’exemple, le client appelle AddEmployee suivi d’un appel GetEmployee pour vérifier si le premier appel a réussi. Le résultat de la demande d’opération GetEmployee s’affiche dans la fenêtre de console cliente. L’opération GetEmployee doit réussir à trouver l’employé et à afficher « trouvé ».
Remarque
Cet exemple montre comment intégrer un substitut pour sérialiser, désérialiser et générer des métadonnées. Il ne montre pas comment brancher une substitution pour la génération de code à partir de métadonnées. Pour savoir comment utiliser un substitut afin de générer du code client, consultez l’exemple Publication WSDL personnalisée.
Pour configurer, générer et exécuter l’exemple
Assurez-vous d’avoir effectué la Procédure d’installation unique pour les exemples Windows Communication Foundation.
Pour générer l’édition C# de la solution, suivez les instructions de Création des exemples Windows Communication Foundation.
Pour exécuter l’exemple dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions figurant dans la rubrique Exécution des exemples Windows Communication Foundation.