DataContractResolver

L’exemple DataContractResolver montre comment les processus de sérialisation et de désérialisation peuvent être personnalisés à l’aide de la classe DataContractResolver. Cet exemple illustre comment utiliser DataContractResolver pour mapper les types CLR vers et depuis une représentation xsi:type pendant la sérialisation et la désérialisation.

Détails de l'exemple

L'exemple définit les types CLR suivants.

using System;
using System.Runtime.Serialization;

namespace Types
{
    [DataContract]
    public class Customer
    {
        [DataMember]
        public string Name { get; set; }
    }

    [DataContract]
    public class VIPCustomer : Customer
    {
        [DataMember]
        public string VipInfo { get; set; }
    }

    [DataContract]
    public class RegularCustomer : Customer
    {
    }

    [DataContract]
    public class PreferredVIPCustomer : VIPCustomer
    {
    }
}

L'exemple charge l'assembly, extrait chacun de ces types, puis les sérialise et les désérialise. Le DataContractResolver est intégré au processus de sérialisation en passant une instance de la classe dérivée de DataContractResolver au constructeur DataContractSerializer, comme indiqué dans l'exemple suivant.

this.serializer = new DataContractSerializer(typeof(Object), null, int.MaxValue, false, true, null, new MyDataContractResolver(assembly));

Dans l'exemple, les types CLR sont ensuite sérialisés comme indiqué dans le code suivant.

Assembly assembly = Assembly.Load(new AssemblyName("Types"));

public void serialize(Type type)
{
    Object instance = Activator.CreateInstance(type);

    Console.WriteLine("----------------------------------------");
    Console.WriteLine();
    Console.WriteLine("Serializing type: {0}", type.Name);
    Console.WriteLine();
    this.buffer = new StringBuilder();
    using (XmlWriter xmlWriter = XmlWriter.Create(this.buffer))
    {
        try
        {
            this.serializer.WriteObject(xmlWriter, instance);
        }
        catch (SerializationException error)
        {
            Console.WriteLine(error.ToString());
        }
    }
    Console.WriteLine(this.buffer.ToString());
}

Les xsi:types sont ensuite désérialisés comme indiqué dans l'exemple de code suivant.

public void deserialize(Type type)
{
    Console.WriteLine();
    Console.WriteLine("Deserializing type: {0}", type.Name);
    Console.WriteLine();
    using (XmlReader xmlReader = XmlReader.Create(new StringReader(this.buffer.ToString())))
    {
        Object obj = this.serializer.ReadObject(xmlReader);
    }
}

Puisque le DataContractResolver personnalisé est passé au constructeur DataContractSerializer, le TryResolveType est appelé pendant la sérialisation pour mapper un type CLR à un xsi:type équivalent. De même, le ResolveName est appelé pendant la désérialisation pour mapper le xsi:type à un type CLR équivalent. Dans cet exemple, le DataContractResolver est défini comme indiqué ci-dessous.

L'exemple de code suivant est une classe dérivée de DataContractResolver.

class MyDataContractResolver : DataContractResolver
{
    private Dictionary<string, XmlDictionaryString> dictionary = new Dictionary<string, XmlDictionaryString>();
    Assembly assembly;

    public MyDataContractResolver(Assembly assembly)
    {
        this.assembly = assembly;
    }

    // Used at deserialization
    // Allows users to map xsi:type name to any Type
    public override Type ResolveName(string typeName, string typeNamespace, DataContractResolver knownTypeResolver)
    {
        XmlDictionaryString tName;
        XmlDictionaryString tNamespace;
        if (dictionary.TryGetValue(typeName, out tName) && dictionary.TryGetValue(typeNamespace, out tNamespace))
        {
            return this.assembly.GetType(tNamespace.Value + "." + tName.Value);
        }
        else
        {
            return null;
        }
    }

    // Used at serialization
    // Maps any Type to a new xsi:type representation
    public override void ResolveType(Type dataContractType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
    {
        string name = dataContractType.Name;
        string namesp = dataContractType.Namespace;
        typeName = new XmlDictionaryString(XmlDictionary.Empty, name, 0);
        typeNamespace = new XmlDictionaryString(XmlDictionary.Empty, namesp, 0);
        if (!dictionary.ContainsKey(dataContractType.Name))
        {
            dictionary.Add(name, typeName);
        }
        if (!dictionary.ContainsKey(dataContractType.Namespace))
        {
            dictionary.Add(namesp, typeNamespace);
        }
    }
}

Dans le cadre de l'exemple, le projet Types génère l'assembly avec tous les types utilisés dans cet exemple. Utilisez ce projet pour ajouter, supprimer ou modifier les types qui seront sérialisés.

Pour utiliser cet exemple

  1. À l’aide de Visual Studio, ouvrez le fichier de solution DCRSample.sln.

  2. Pour exécuter la solution, appuyez sur F5.

Voir aussi