■ はじめに
https://dk521123.hatenablog.com/entry/22166698で、XMLシリアライズ・デシリアライズを行ったが、 XmlSerializerクラスでは、Dictionary をシリアル化できない。 色々な方法があるようだが、DataContractSerializerクラスでやるのが 一番スマートそうなので、纏める。
■ DataContractSerializerクラス
* .NET3.0 から
使用上の注意
* プロジェクトの参照設定に「System.Runtime.Serialization.dll」を追加する必要がある * シリアライズするクラスに[DataContract]属性を、フィールドに[DataMember]属性を付与する必要がある => DataMemberを付加させないと、シリアル化の対象にならない
XmlSerializerクラスとの違い
* HashtableやDictionaryなどもシリアル化できる * パフォーマンスもいいらしい => XmlSerializerクラスは、シリアル化効率が悪く、シリアル化できる型も限られる
■ サンプル
例1
using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text; using System.Windows.Forms; using System.Xml; namespace SampleForm { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Person person = new Person() { Name = "Mike", Birthday = DateTime.Now, NumberOfFamily = 4, Memos = new Dictionary<int, string>() { { 1, "Hello"}, { 2, "World!!"}, { 3, "Thank you for everything!!"}, { 4, "Ciao!"} } }; var filePath = @"hello.xml"; Write<Person>(person, filePath); var clonePerson = Read<Person>(filePath); this.label1.Text = string.Format("{0}\n{1}\n{2}\n", clonePerson.Name, clonePerson.Birthday, clonePerson.NumberOfFamily); foreach (var memo in clonePerson.Memos) { this.label1.Text = this.label1.Text + string.Format("\n{0} : {1}", memo.Key, memo.Value); } } private static T Read<T>(string filePath) { var serializer = new DataContractSerializer(typeof(T)); using (var reader = XmlReader.Create(filePath)) { return (T)serializer.ReadObject(reader); } } private static void Write<T>(T instace, string filePath) { var settings = new XmlWriterSettings { Encoding = new UTF8Encoding(false) }; var serializer = new DataContractSerializer(typeof(T)); using (var writer = XmlWriter.Create(filePath, settings)) { serializer.WriteObject(writer, instace); } } } [DataContract] public class Person { [DataMember] public string Name { get; set; } [DataMember] public DateTime Birthday { get; set; } [DataMember] public int NumberOfFamily { get; set; } [DataMember] public Dictionary<int, string> Memos { get; set; } } }出力結果
Mike 2019/02/21 22:03:02 4 1 : Hello 2 : World!! 3 : Thank you for everything!! 4 : Ciao!
例2
[DataContract] public class Person { [DataMember] public string Name { get; set; } [DataMember] public int Age { get; set; } public Person(string newName, int newAge) { this.Name = newName; this.Age = newAge; } } public static T Copy<T>(T source) where T : class { T result = null; using (var ms = new System.IO.MemoryStream()) { // Serializer the User object to the stream. DataContractSerializer ser = new DataContractSerializer(typeof(T)); ser.WriteObject(ms, source); ms.Position = 0; result = ser.ReadObject(ms) as T; } return result; }シリアライズ
public static Stream Serialize<T>(T target) { var formatter = new BinaryFormatter(); var stream = new MemoryStream(); formatter.Serialize(stream, target); stream.Seek(0, SeekOrigin.Begin); return stream; }デシリアライズ
public static T Deserialize<T>(Stream target) { var formatter = new BinaryFormatter(); T returnValue = (T) formatter.Deserialize(target); return returnValue; }
参考文献
https://dobon.net/vb/dotnet/file/datacontractserializer.htmlhttps://qiita.com/koara-local/items/5307f26d8cc9f33be038
https://qiita.com/K-Masa/items/9899a0e2b6378580a457
http://gushwell.ldblog.jp/archives/50820429.html
http://msdn.microsoft.com/ja-jp/library/aa904194.aspx
http://d.hatena.ne.jp/hilapon/20120301/1330569751
関連記事
XML関連
C# でXMLファイルを扱うには ~ 入門編 ~https://dk521123.hatenablog.com/entry/32868509
C# でXMLシリアライズ・デシリアライズ ~ XmlSerializerクラス ~
https://dk521123.hatenablog.com/entry/22166698