DataContract
Moteur de sérialisation de WCF.
Utilise l'assembly System.Runtime.Serialization.
Liens
DataContractSerializer vs XmlSerializer
+ |
sérialise les propriétés et attributs marqués [DataMember] même s'ils ne sont pas public
|
+ |
permet de sérialiser les classes implémentant IDictionary, ce que ne permet pas XmlSerializer
|
+ |
sérialise uniquement les propriétés et attributs marqués [DataMember], là où XmlSerializer sérialise tout ce qui n'est pas exclu avec [XmlIgnore]
|
+ |
possibilité de spécifier l'ordre de sérialisation avec [DataMember(Order = 0)]
|
+ |
meilleurs performances que XmlSerializer
|
- |
une classe marquée [DataMember] ne peut hériter que de classes elles aussi marquées [DataMember]
|
Exemple
|
[KnownType(typeof(Classe2))]
[DataContract(IsReference = true)]
public class Classe1
{
[DataMember]
public Classe2 Classe2 { get; set; }
public Classe3 Classe3 { get; set; }
[OnDeserialized]
void MethodOnDeserialized(StreamingContext context)
{
Classe3 = new Classe3();
}
[OnDeserializing]
void MethodOnDeserializing(StreamingContext context)
{ }
}
[CollectionDataContract]
public class MegaList : List<int>
{ }
|
Attention DataContract ne permet pas de sérialiser les propriétés contenues dans un type Collection.
|
[CollectionDataContract]
public class MegaList : List<int>
{
[DataMember]
public string Propriété { get; set; }
}
[DataContract]
public class MegaList
{
[DataMember]
public string Propriété { get; set; }
[DataMember]
public List<int> List { get; set; }
}
|
Sérialisation
|
var serializer = new DataContractJsonSerializer(dataToSerialize.GetType());
var serializer = new DataContractSerializer(dataToSerialize.GetType());
using (var stream = new FileStream(destinationFilePath, FileMode.Create)) // dans un fichier. FileMode.Create : create or override
using (var stream = new MemoryStream()) // dans un string
{
using (var writer = XmlDictionaryWriter.CreateTextWriter(stream)) // XML
using (var writer = XmlWriter.Create(stream, new XmlWriterSettings() { Indent = true })) // XML avec indentation
using (var writer = XmlDictionaryWriter.CreateMtomWriter(stream, Encoding.UTF8, int.MaxValue, "")) // MTOM
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream)) // Binary
{
serializer.WriteObject(writer, dataToSerialize);
writer.Flush();
dataString = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
}
}
|
Désérialisation
|
using (var stream = new FileStream(dataFilePath, FileMode.Open)) // depuis un fichier
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(dataString))) // depuis un string
{
using (var reader = XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max))
{
var dataContractSerializer = new DataContractSerializer(typeof(MyData));
var myData = dataContractSerializer.ReadObject(reader) as MyData;
}
}
|
Attributs DataContract, DataMember
Par défaut
Si la classe à sérialiser n'est pas décorée avec l'attribut DataContract, toutes les propriétés public sont sérialisées.
|
public class MaClasse
{
public int P1 { get; set; }
[IgnoreDataMember]
public string P2 { get; set; }
|
 |
DataMember peut être utilisé même si DataContract ne décore pas la classe. |
Attribut DataContract
Si l'attribut DataContract décore la classe, toutes les propriétés et champs décorées avec DataMember seront sérialisées, même s'ils sont private.
|
[DataContract]
public class MaClasse
{
[DataMember]
public int P1 { get; set; }
[DataMember]
private int _p2 { get; set; }
public string P3 { get; set; }
[DataMember(Name = "property3")]
public int P4 { get; set; }
|
CollectionDataContract
|
[CollectionDataContract(ItemName = "SItem")]
public class SuperList : List<int> {}
[CollectionDataContract(KeyName = "SKey", ValueName = "SValue")]
public class SuperDico : Dictionary<int, string>
public class MaClasse
{
public SuperList SList { get; private set; }
public SuperDico SDico { get; private set; }
|
|
<SList xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:int>1</d2p1:int>
</SList>
<SDico xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:KeyValueOfintstring>
<d2p1:Key>1</d2p1:Key>
<d2p1:Value>un</d2p1:Value>
</d2p1:KeyValueOfintstring>
<SList>
<SItem>1</SItem>
<int>1</int>
</SList>
<SDico>
<KeyValueOfintstring>
<SKey>1</SKey>
<SValue>un</SValue>
</KeyValueOfintstring>
|
Polymorphisme
|
[KnownType(typeof(InhertedClass))]
[KnownType("GetDerivedTypes")]
public class ParentClass
{
public int P1 { get; set; }
public static IEnumerable<Type> GetDerivedTypes()
{
return typeof(ParentClass).Assembly.GetTypes().
Where(type => typeof(ParentClass).IsAssignableFrom(type));
}
}
public class InhertedClass : ParentClass
{
public int P2 { get; set; }
}
var dataContractSerializer = new DataContractSerializer(typeof(ParentClass));
|
Namespace
|
<?xml version="1.0" encoding="utf-8"?>
<MaClasse xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/MonNamespace">
|
|
[assembly:ContractNamespace("http://www.domaine.fr/service/v1.0.0", ClrNamespace = "MonNamespace")]
// force le xmlns pour MaClasse
[DataContract(Namespace = "http://www.domaine.fr/service/v2.0.0")]
public class MaClasse {}
|