DataContractResolver

DataContractResolver 範例示範如何使用 DataContractResolver 類別來自訂序列化和還原序列化流程。 此範例會示範如何使用 DataContractResolver,在序列化和還原序列化期間來回對應 CLR 型別與 xsi:type 表示。

範例詳細資料

此範例會定義下列 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
    {
    }
}

此範例會載入組件、擷取其中每個型別,然後序列化和還原序列化這些型別。 系統會將 DataContractResolver 衍生類別的執行個體傳遞給 DataContractResolver 建構函式,藉以將 DataContractSerializer 插入序列化程序中,如下列範例所示。

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

然後,此範例會序列化這些 CLR 型別,如下列程式碼範例所示。

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

然後,此範例會還原序列化這些 xsi:type,如下列程式碼範例所示。

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

因為自訂 DataContractResolver 已傳入 DataContractSerializer 建構函式,所以系統會在序列化期間呼叫 TryResolveType,以便將 CLR 型別對應至對等的 xsi:type。 同樣地,系統會在還原序列化期間呼叫 ResolveName,以便將 xsi:type 對應至對等的 CLR 型別。 在此範例中,DataContractResolver 定義的方式如下列範例所示。

下列程式碼範例是從 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);
        }
    }
}

在此範例中,類型專案會產生包含此範例中使用之所有類型的組件。 使用此專案加入、移除或修改即將序列化的類型。

若要使用這個範例

  1. 使用 Visual Studio 開啟 DCRSample.sln 方案檔。

  2. 若要執行此方案,請按 F5

另請參閱