DataContractResolver
In questo esempio viene descritto come è possibile personalizzare processi di serializzazione e deserializzazione tramite la classe DataContractResolver. L'esempio illustra come aggiungere tipi noti in modo dinamico durante la serializzazione e la deserializzazione.
Dettagli dell'esempio
Nell'esempio di codice riportato di seguito viene mostrato un assembly con i tipi seguenti.
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'esempio analizza l'assembly, estrae ognuno dei tipi e quindi procede a serializzarli e deserializzarli. Il DataContractResolver viene collegato al costruttore DataContractSerializer, illustrato nell'esempio seguente.
this.serializer = new DataContractSerializer(typeof(Object), null, int.MaxValue, false, true, null, new MyDataContractResolver(assembly));
Nell'esempio di codice seguente viene illustrato come serializzare i tipi nell'assembly.
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());
}
Nell'esempio di codice seguente viene illustrato come deserializzare i tipi nell'assembly.
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);
}
}
Quando un DataContractResolver viene collegato al costruttore DataContractSerializer, viene sempre utilizzata la logica definita nel resolver del contratto dati invece della logica di serializzazione e deserializzazione di tipi noti. In particolare, sono presenti due importanti metodi nel DataContractResolver. Il metodo TryResolveType viene utilizzato durante la serializzazione per eseguire il mapping di qualsiasi tipo a una nuova rappresentazione xsi:type e il metodo TryResolveType viene utilizzato durante la deserializzazione per eseguire il mapping del xsi:type a qualsiasi tipo. In questo esempio, il DataContractResolver viene definito come illustrato nell'esempio seguente.
L'esempio di codice riportato di seguito è una classe che deriva da 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);
}
}
}
Come parte dell'esempio, il progetto Types genera l'assembly con tutti i tipi utilizzati in questo esempio. Utilizzare il progetto per aggiungere, rimuovere o modificare i tipi che saranno serializzati.
Per utilizzare questo esempio
Utilizzando Visual Studio 2010, aprire il file della soluzione DCRSample.sln.
Per eseguire la soluzione, premere F5
![]() |
---|
È possibile che gli esempi siano già installati nel computer. Verificare la directory seguente (impostazione predefinita) prima di continuare.
<UnitàInstallazione>:\WF_WCF_Samples
Se questa directory non esiste, andare alla pagina relativa agli esempi di Windows Communication Foundation (WCF) e Windows Workflow Foundation (WF) per .NET Framework 4 per scaricare tutti gli esempi di Windows Communication Foundation (WCF) e WF. Questo esempio si trova nella directory seguente.
<UnitàInstallazione>:\WF_WCF_Samples\WCF\Basic\Contract\Data\DataContractResolver
|