Freigeben über


DataContractResolver

Das DataContractResolver-Beispiel veranschaulicht, wie die Serialisierungs- und Deserialisierungsprozesse mithilfe der DataContractResolver Klasse angepasst werden können. In diesem Beispiel wird veranschaulicht, wie DataContractResolver verwendet wird, um bei der Serialisierung und der Deserialisierung CLR-Typen einer xsi:type-Darstellung zuzuordnen bzw. diese Zuordnung wieder aufzuheben.

Beispieldetails

Im Beispiel werden die folgenden CLR-Typen definiert.

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

Die Assembly wird im Beispiel geladen, wobei jeder dieser Typen extrahiert und dann serialisiert und deserialisiert wird. Das DataContractResolver Wird an den Serialisierungsprozess angeschlossen, indem eine Instanz der DataContractResolverabgeleiteten Klasse an den DataContractSerializer Konstruktor übergeben wird, wie im folgenden Beispiel gezeigt.

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

Anschließend werden die CLR-Typen serialisiert, wie im folgenden Codebeispiel gezeigt.

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

Dann werden die xsi:-Typen deserialisiert, wie im folgenden Codebeispiel gezeigt.

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

Da der benutzerdefinierte DataContractResolver an den DataContractSerializer-Konstruktor übergeben wird, wird TryResolveType während der Serialisierung aufgerufen, um einen CLR-Typ einem entsprechenden xsi:type zuzuordnen. Ebenso wird die ResolveName während der Deserialisierung aufgerufen, um xsi:type einem entsprechenden CLR-Typ zuzuordnen. In diesem Beispiel wird die DataContractResolver wie im folgenden Beispiel definiert.

Das folgende Codebeispiel zeigt eine Klasse, die von DataContractResolver abgeleitet ist.

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

Im Rahmen des Beispiels generiert das Projekt "Types" die Assembly mit allen Typen, die in diesem Beispiel verwendet werden. Verwenden Sie dieses Projekt, um die Typen hinzuzufügen, zu entfernen oder zu ändern, die serialisiert werden.

So verwenden Sie dieses Beispiel

  1. Öffnen Sie mit Visual Studio die DCRSample.sln Projektmappendatei.

  2. Drücken Sie F5, um die Lösung auszuführen.

Siehe auch