DataContractResolver

W przykładzie DataContractResolver pokazano, jak można dostosować procesy serializacji i deserializacji przy użyciu DataContractResolver klasy . W tym przykładzie pokazano, jak za pomocą elementu DataContractResolver mapować typy CLR na i z reprezentacji xsi:type podczas serializacji i deserializacji.

Przykładowe szczegóły

W przykładzie zdefiniowano następujące typy CLR.

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
    {
    }
}

Przykład ładuje zestaw, wyodrębnia każdy z tych typów, a następnie serializuje je i deserializuje. Element DataContractResolver jest podłączony do procesu serializacji, przekazując wystąpienie DataContractResolverklasy pochodnej do konstruktora DataContractSerializer , jak pokazano w poniższym przykładzie.

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

Następnie przykład serializuje typy CLR, jak pokazano w poniższym przykładzie kodu.

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());
}

Następnie przykład deserializuje xsi:types, jak pokazano w poniższym przykładzie kodu.

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);
    }
}

Ponieważ element niestandardowy DataContractResolver jest przekazywany do konstruktora DataContractSerializer , TryResolveType element jest wywoływany podczas serializacji w celu mapowania typu CLR na odpowiednik xsi:type. Podobnie parametr jest wywoływany ResolveName podczas deserializacji, aby zamapować xsi:type element na równoważny typ CLR. W tym przykładzie element DataContractResolver jest zdefiniowany, jak pokazano w poniższym przykładzie.

Poniższy przykład kodu to klasa wyprowadzona z DataContractResolverklasy .

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);
        }
    }
}

W ramach przykładu projekt Types generuje zestaw ze wszystkimi typami używanymi w tym przykładzie. Ten projekt służy do dodawania, usuwania lub modyfikowania typów, które będą serializowane.

Aby użyć tego przykładu

  1. Za pomocą programu Visual Studio otwórz plik rozwiązania DCRSample.sln.

  2. Aby uruchomić rozwiązanie, naciśnij klawisz F5.

Zobacz też