Il faut ajouter la référence ''System.Runtime.Serialization''.
====Préparation des classes====
[DataContract]
class BatchPoco
{
[DataMember]
public String Valeur { get; private set; }
}
Tous les éléments sérialisés doivent être ''DataContract''. Donc si une classe fait référence à une autre classe non native, il faut aussi la déclarer :
[DataContract]
class Class1
{
[DataMember]
public String Valeur1 { get; private set; }
}
[DataContract]
class Class2
{
[DataMember]
public Class1 Valeur2 { get; private set; }
}
On peut aussi avoir des boucles : la classe 1 dépend de la 2 et inversement. Dans ce cas, il faut indiquer qu'il ne faut pas sérialiser tous les éléments mais qu'il faut préserver les références (liens).
[DataContract(IsReference = true)]
class Class1
{
[DataMember]
public Class2 Valeur1 { get; private set; }
}
[DataContract(IsReference = true)]
class Class2
{
[DataMember]
public Class1 Valeur2 { get; private set; }
}
''IsReference'' ne marche qu'avec la sérialisation au format XML, pas JSON.
* Héritage
Si on souhaite sérialiser une classe dont un des champs n'est renseigné que par un parent ou une interface, il faut déclarer explicitement tous les types de classes.
[DataContract]
class IAnimal{}
[DataContract]
class Chat : IAnimal{}
[DataContract]
class Chien : IAnimal{}
[DataContract]
[KnownType(typeof(Chat))]
[KnownType(typeof(Chien))]
class Foret
{
[DataMember]
List faune;
}
Sans ''KnownType'', il va y avoir une erreur :
Type 'XXXX' with data contract name 'YYYY' is not expected. Add any types not known statically to the list of known types - for example,
by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
[[https://stackoverflow.com/questions/30210393/exception-during-the-serialization-type-with-data-contract-name-is-not-expecte/30214583|Exception during the serialization - Type with data contract name is not expected]] {{ :lang:csharp:serialisation:c_-_exception_during_the_serialization_-_type_with_data_contract_name_is_not_expected_-_stack_overflow_2020-04-27_8_18_17_am_.html |Archive du 13/05/2015 le 27/04/2020}}
[[https://docs.microsoft.com/en-us/archive/blogs/youssefm/understanding-known-types/|Understanding Known Types]] {{ :lang:csharp:serialisation:understanding_known_types_microsoft_docs_2020-04-27_8_18_33_am_.html |Archive du 22/04/2009 le 27/04/2020}}
====Sérialisation en XML====
* Charger
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
DataContractSerializer ser = new DataContractSerializer(typeof(BatchPoco));
using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
{
using (MemoryStream ms = new MemoryStream())
{
try
{
_batch = (BatchPoco)ser.ReadObject(reader, true);
}
catch (SerializationException)
{
// Fichier non valide.
}
}
}
}
* Enregistrer
using (MemoryStream ms = new MemoryStream())
{
DataContractSerializer ser = new DataContractSerializer(typeof(BatchPoco));
ser.WriteObject(ms, _batch);
byte[] xml = ms.ToArray();
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
fs.Write(xml, 0, xml.Length);
}
}
[[https://docs.microsoft.com/fr-fr/dotnet/framework/wcf/samples/datacontractserializer-sample|DataContractSerializer, exemple]] {{ :lang:csharp:serialisation:datacontractserializer_exemple_-_wcf_microsoft_docs_2020-04-27_8_18_42_am_.html |Archive du 03/30/2017 le 27/04/2020}}
====Sérialisation en JSON====
C'est la même chose avec ''DataContractJsonSerializer''.
[[https://docs.microsoft.com/fr-fr/dotnet/framework/wcf/feature-details/how-to-serialize-and-deserialize-json-data|How to use DataContractJsonSerializer]] {{ :lang:csharp:serialisation:comment_utiliser_datacontractjsonserializer_-_wcf_microsoft_docs_2020-04-27_8_19_16_am_.html |Archive du 25/03/2019 le 27/04/2020}}
TODO : Cette classe est dépréciée au profit du namespace ''System.Text.Json''.
====Initialisation dans le constructeur====
Le constructeur, et les propriétés initialisées dans leurs déclarations, ne sont pas appelés lors de la désérialisation. Il est nécessaire de le faire manuellement.
private object Mutex { get; set; };
private void InitNoDataMember()
{
Mutex = new object();
}
[OnDeserializing]
private void SetValuesOnDeserializing(StreamingContext context)
{
InitNoDataMember();
}
public Constructeur()
{
InitNoDataMember();
}
Il existe :
* ''OnSerializing'' : fonction exécutée lors de la sérialisation de l'instance.
* ''OnSerialized'' : fonction exécutée après la sérialisation de l'instance.
* ''OnDeserializing'' : fonction exécutée lors de la désérialisation de l'instance.
* ''OnDeserialized'' : fonction exécutée après la désérialisation de l'instance.
En cas d'héritage, ''OnSerializing'' est appelée pour le parent, puis pour l'enfant et enfin les ''OnSerialized'' sont appelées. Puis la désérialisation passe à l'objet suivant.