■ はじめに
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