Utilisation d'un programme de résolution de contrat de données
Un programme de résolution de contrat de données vous permet de configurer des types connus de manière dynamique. Les types connus sont nécessaires lors de la sérialisation ou de la désérialisation d'un type non attendu par un contrat de données. Pour plus d’informations sur les types connus, consultez Types connus de contrat de données. Les types connus sont généralement spécifiés statiquement. Cela signifie que vous devez connaître tous les types possibles qu'une opération peut recevoir pendant son implémentation. Voici les scénarios où cela n'est pas vrai et où il est important de pouvoir spécifier les types connus de façon dynamique.
Création d'un programme de résolution de contrat de données
La création d'un programme de résolution de contrat de données implique l'implémentation de deux méthodes, TryResolveType et ResolveName. Ces deux méthodes implémentent des rappels utilisés respectivement lors de la sérialisation et de la désérialisation. La méthode TryResolveType est appelée lors de la sérialisation, prend un type de contrat de données et le mappe à un nom et espace de noms xsi:type
. La méthode ResolveName est appelée lors de la désérialisation, prend un nom et espace de noms xsi:type
et le résout en type de contrat de données. Ces deux méthodes ont un paramètre knownTypeResolver
qui peut être utilisé pour utiliser le programme de résolution de type connu par défaut dans votre implémentation.
L'exemple suivant indique comment implémenter un objet DataContractResolver pour un mappage sur et à partir d'un type de contrat de données nommé Customer
, dérivé d'un type de contrat de données Person
.
public class MyCustomerResolver : DataContractResolver
{
public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
if (dataContractType == typeof(Customer))
{
XmlDictionary dictionary = new XmlDictionary();
typeName = dictionary.Add("SomeCustomer");
typeNamespace = dictionary.Add("http://tempuri.com");
return true;
}
else
{
return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace);
}
}
public override Type ResolveName(string typeName, string typeNamespace, DataContractResolver knownTypeResolver)
{
if (typeName == "SomeCustomer" && typeNamespace == "http://tempuri.com")
{
return typeof(Customer);
}
else
{
return knownTypeResolver.ResolveName(typeName, typeNamespace, null);
}
}
}
Une fois que vous avez défini un objet DataContractResolver, vous pouvez l'utiliser en le transmettant au constructeur DataContractSerializer, comme indiqué dans l'exemple suivant.
XmlObjectSerializer serializer = new DataContractSerializer(typeof(Customer), null, Int32.MaxValue, false, false, null, new MyCustomerResolver());
Vous pouvez spécifier un objet DataContractResolver dans un appel aux méthodes DataContractSerializer.ReadObject ou DataContractSerializer.WriteObject, comme indiqué dans l'exemple suivant.
MemoryStream ms = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(Customer));
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(XmlWriter.Create(ms));
serializer.WriteObject(writer, new Customer(), new MyCustomerResolver());
writer.Flush();
ms.Position = 0;
Console.WriteLine(((Customer)serializer.ReadObject(XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(ms)), false, new MyCustomerResolver()));
Vous pouvez également le définir sur l'objet DataContractSerializerOperationBehavior comme le montre l'exemple suivant.
ServiceHost host = new ServiceHost(typeof(MyService));
ContractDescription cd = host.Description.Endpoints[0].Contract;
OperationDescription myOperationDescription = cd.Operations.Find("Echo");
DataContractSerializerOperationBehavior serializerBehavior = myOperationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (serializerBehavior == null)
{
serializerBehavior = new DataContractSerializerOperationBehavior(myOperationDescription);
myOperationDescription.Behaviors.Add(serializerBehavior);
}
SerializerBehavior.DataContractResolver = new MyCustomerResolver();
Spécifiez de façon déclarative un programme de résolution de contrat de données en implémentant un attribut qui peut être appliqué à un service. Pour plus d’informations, consultez exemple KnownAssemblyAttribute. Cet exemple implémente un attribut appelé « KnownAssembly » qui ajoute un programme de résolution de contrat de données personnalisé au comportement du service.