restofwaterimpのぎじゅつMemo

SIerに所属。企画から運用まで幅広くやってます。C#中心に書いてます。

【C#】C#プログラミングのイディオム(12章)シリアル化、逆シリアル化(前半 XML)

前回の続き

restofwaterimp.hatenablog.com

11章でXMLファイルの操作ということで、XDocumentやXElementを利用した 操作が中心であった。

この章ではファイルの操作ではなく、ファイルのやりとりが中心の説明となっている。

シリアル化、逆シリアル化って?

f:id:restofwaterimp:20181011063653p:plain

シリアル化はオブジェクトの状態をネットワークを通じて転送できる形式やファイルに保存できる形式。 シリアル化したデータを元のオブジェクトに戻すことを逆シリアル化という。

この変換には System.Runtime.Serialization名前空間のDataContractSerializerを利用する。

docs.microsoft.com

オブジェクトを起点に、 WriteObjectがシリアル化、ReadObjectが逆シリアル化で、シリアルという特別な言葉ではなく、読み書きというメソッド名なので、 ファイルの読み書きと同じ感覚で利用できるのでは?と想定される。

書籍の例を元に記述(XMLファイル)

    class MainClass
    {
        public static void Main(string[] args)
        {
            var novel = new Novel
            {
                Author = "Jemus du Horgan",
                Title = "Continue to planet",
                Published = 1997,
            };

            var novels = new Novel[]{
                new Novel{
                    Author = "Jemus du Horgan",
                Title = "Continue to planet",
                Published = 1997,
                },
                new Novel{
                    Author = "H/G wells",
                Title = "Time machine",
                Published = 1895,
                }
            };

            var settings = new XmlWriterSettings
            {
                Encoding = new System.Text.UTF8Encoding(false),
                Indent = true,
                IndentChars = " ",
            };

            /*シリアル化*/
            using(var writer = XmlWriter.Create("novel.xml", settings)){
                var serializer = new DataContractSerializer(novels.GetType());
                serializer.WriteObject(writer, novels);
            }

            /*逆シリアル*/
            using(XmlReader reader = XmlReader.Create("novel.xml")){
                var serializer = new DataContractSerializer(typeof(Novel[]));
                var readnovels = serializer.ReadObject(reader) as Novel[];
                foreach(var readnovel in readnovels){
                    Console.WriteLine(readnovel);
                }
            }
        }


    }

    public class Novel{
        public string Title { get; set; }
        public string Author { get; set; }
        public int Published { get; set; }
        public override string ToString(){
            return string.Format("[Title={0}, Author={1}, Published=m{2}]", Title, Author, Published);
        }
    }
}

XMLWriterSettingでファイルの形式を決めないと、デフォルトのまま出力されます。 (改行なしのXMLファイルができます)

DataContractSerializerの代わりにXmlSerializerを利用することもできます。 本書ではXMLでデータを受け渡しをするにはこちらの方が良いと記述されております。

           using (var writer2 = XmlWriter.Create("novel.xml")){
                var serializer2 = new XmlSerializer(novel.GetType());
                serializer2.Serialize(writer2, book); //シリアル化するオブジェクト、書き込むための元データ
            }

/*シリアル化するもとのオブジェクト*/
    public class Novel{
        public string Title { get; set; }
        public string Author { get; set; }
        [XmlIgnore] //Ignoreをつけると、シリアル化対象外となる
        public int Published { get; set; }
        public override string ToString(){
            return string.Format("[Title={0}, Author={1}, Published=m{2}]", Title, Author, Published);
        }
    }

出力するとこんな感じに <?xml version="1.0" encoding="utf-8"?>Continue PlanetJames P Hogan

妖精名は宣言した時のプロパティ名になります。 もし、変更したい場合は [XmlElement(ElementName="xxxx")] を変更したいプロパティに記述するとできます。

XmlSerializer.Serialize Method (System.Xml.Serialization) | Microsoft Docs

DataContractSerializer
Serializes and deserializes an instance of a type into an XML stream or document using a supplied data contract. This class cannot be inherited.

XmlSerializer クラスの使用 | Microsoft Docs

それぞれのクラスの比較は下記のサイトに記載があったので、ご確認あれ。

DataContractSerializerを使って、オブジェクトのXMLシリアル化、逆シリアル化を行う - .NET Tips (VB.NET,C#...)

なんで、同じような機能があるのだろうと疑問に思い、検索してみたところ

シリアル化のガイドライン

と、MSからガイドラインがでていることを見つけた。

XMLSerializerを利用すると、Elementの詳細まで定義できるので、細かな設定が必要ならば、こちらの方が使いやすい。

とりとめないですが、つづく(JSONへ)