C#の標準シリアライズ・デシリアライズを簡単にまとめてみた

#まとめてみた
設定とか、何かしらのオブジェクトをざっと保存して、さっと読み込みたいなぁなんて思った時に、シリアライザーという言葉が目に付きました。

でもなんか色々ある...。
というわけでちょっと、簡単に使える感じにまとめてみました。

個人的には ReactiveProperty がシリアライズできる、できないみたいなところが重要です。
でも、そうなると XmlSerializer しか使えない。
Slim とかもできないみたいですけど、ドキュメントを漁っても ReactivePropertyのシリアライズに関する記事がない...。

探し方が悪い？
そういった使い方をしないとか？

なんちゃってプログラマーの私にはわからない...。

#標準のシリアライザー達
- **XmlSerializer**
    - 結構汎用的というか、使い勝手がいいイメージのあるシリアライザー
    - ReactiveProperty\<T> とかもシリアライズできる。（他はなんかできなかった…。シリアライズはカスタムできるらしいので、何かしらこねこねすればいけるんでしょうか？）
    - 適用にプロパティを持ったクラスがあるなら、この子に放り込めばいい感じにしてくれる。安パイ的な存在。
    - 空のコンストラクタが必須。

- **BinaryFormatter**
    - バイナリで高速。（でも場合によりけりてきな文言が目に付く...）
    - ReactivePropertyはシリアライズできない。
    - クラス属性に [Serializeble] を宣言する。
    - 空のコンストラクタが必須。

- **DataContractSerializer**
    - 他ではできないDictionaryとか、ほとんどのオブジェクトをシリアライズできる。シリアライザーとしては強力な機能を持っているらしいです。
    - ReactivePropertyはシリアライズできない。
    - クラス属性に [DataContract] を宣言する。
    - プロパティには [DataMember] を付けないとシリアライズされない。Orderとかでシリアライズ順序を指定できる。
    - 空のコンストラクタがいらない。（シリアライズ時にコンストラクタが呼び出されない）

- **DataContractJsonSerializer**
    - オブジェクトをJSON形式でシリアライズ・デシリアライズできる。
    - DataContractSerializerよりも柔軟性がある。
    - 後は、XMLとの相互変換するような機能がある。（インテリセンスのオーバーロードに出たのを見ただけで試してないですが…）
    - JSON.Netとかライブラリがあるようなのでそちらを使った方がよい？
    - ReactivePropertyはシリアライズできない。

- **XamlWriter**
    - ButtonとかのUI要素をシリアライズできる。
    - 画面レイアウトの保存とかに使える？

- **XamlReader**
    - ButtonとかのUI要素をデシリアライズできる。
    - 画面レイアウトの復元とかに使える？


以下、コードです。

```c#

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Windows.Markup;
using System.Xml;
using System.Xml.Serialization;

namespace Serializers
{
    public static class XLizer
    {
        /// <summary>
        /// <see cref="XmlWriter"/> のネームスペース設定
        /// </summary>
        private static XmlSerializerNamespaces xmlWriterEmptyNameSpace { get { var empty = new XmlSerializerNamespaces(); empty.Add("", ""); return empty; } }

        /// <summary>
        /// <see cref="XmlWriter"/> のシリアライズ設定
        /// </summary>
        private static XmlWriterSettings xmlWriterSettings { get { return new XmlWriterSettings { Indent = true }; } }

        /// <summary>
        /// <see cref="XmlReader"/> のデシリアライズ設定
        /// </summary>
        private static XmlReaderSettings xmlReaderSettings { get { return new XmlReaderSettings { CheckCharacters = false }; } }

        /// <summary>
        /// <see cref="DataContractJsonSerializer"/> のシリアライズ設定
        /// </summary>
        //private static DataContractJsonSerializerSettings dataContractJsonSerializerSettings { get { return new DataContractJsonSerializerSettings { }; } }

        /// <summary>
        /// <para><see cref="XmlSerializer"/> を使用して <see cref="object"/> をシリアライズします。</para>
        /// </summary>
        public static bool XmlSerialize<T>(string filePath, T dataObject)
        {
            try {

                using XmlWriter xmlWriter =
                    XmlWriter.Create(
                        filePath,
                        xmlWriterSettings);

                XmlSerializer xmlSerializer =
                    new XmlSerializer(
                        typeof(T));

                xmlSerializer.Serialize(
                    xmlWriter,
                    dataObject,
                    xmlWriterEmptyNameSpace);

            } catch {
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="XmlSerializer"/> を使用して <see cref="object"/> をデシリアライズします。</para>
        /// </summary>
        public static bool XmlDeserialize<T>(string filePath, out T dataObject)
        {
            try {

                using XmlReader xmlReader =
                    XmlReader.Create(
                        filePath,
                        xmlReaderSettings);

                XmlSerializer xmlSerializer =
                    new XmlSerializer(
                        typeof(T));

                var obj =
                    xmlSerializer.Deserialize(
                        xmlReader);

                dataObject = (T)obj;

            } catch {
                dataObject = default;
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="BinaryFormatter"/> を使用して <see cref="object"/> をシリアライズします。</para>
        /// <code>
        ///     <para>[<see cref="Serializable"/>]</para>
        ///     <para>class MyClass { ... }</para>
        /// </code>
        /// </summary>
        public static bool BinarySerialize<T>(string filePath, T dataObject)
        {
            try {

                using FileStream fileStream =
                    new FileStream(
                        filePath,
                        FileMode.Create);

                BinaryFormatter binaryFormatter =
                    new BinaryFormatter();

                binaryFormatter.Serialize(
                    fileStream,
                    dataObject);

            } catch {
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="BinaryFormatter"/> を使用して <see cref="object"/> をデシリアライズします。</para>
        /// </summary>
        public static bool BinaryDeserialize<T>(string filePath, out T dataObject)
        {
            try {

                using FileStream fileStream =
                    new FileStream(
                        filePath,
                        FileMode.Open);

                BinaryFormatter binaryFormatter =
                    new BinaryFormatter();

                var obj =
                    binaryFormatter.Deserialize(
                        fileStream);

                dataObject = (T)obj;

            } catch {
                dataObject = default;
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="DataContractSerializer"/> を使用して <see cref="object"/> をシリアライズします。</para>
        /// <code>
        ///     <para>[<see cref="DataContract"/>]</para>
        ///     <para>class MyClass { ... }</para>
        /// </code>
        /// <code>
        ///     <para>[<see cref="DataMember"/>]</para>
        ///     <para>string Field { ... }</para>
        /// </code>
        /// </summary>
        public static bool DataContractSerialize<T>(string filePath, T dataObject)
        {
            try {

                using XmlWriter xmlWriter =
                    XmlWriter.Create(
                        filePath,
                        xmlWriterSettings);

                DataContractSerializer dataContractSerializer =
                    new DataContractSerializer(
                        typeof(T));

                dataContractSerializer.WriteObject(
                    xmlWriter,
                    dataObject);

            } catch {
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="DataContractSerializer"/> を使用して <see cref="object"/> をシリアライズします。</para>
        /// </summary>
        public static bool DataContractDeserialize<T>(string filePath, out T dataObject)
        {
            try {

                using XmlReader xmlReader =
                    XmlReader.Create(
                        filePath,
                        xmlReaderSettings);

                DataContractSerializer dataContractSerializer =
                    new DataContractSerializer(
                        typeof(T));

                var obj =
                    dataContractSerializer.ReadObject(
                        xmlReader);

                dataObject = (T)obj;

            } catch {
                dataObject = default;
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="DataContractJsonSerializer"/> を使用して <see cref="object"/> をシリアライズします。</para>
        /// <code>
        ///     <para>[<see cref="DataContract"/>]</para>
        ///     <para>class MyClass { ... }</para>
        /// </code>
        /// <code>
        ///     <para>[<see cref="DataMember"/>]</para>
        ///     <para>string Field { ... }</para>
        /// </code>
        /// </summary>
        public static bool DataContractJsonSerialize<T>(string filePath, T dataObject)
        {
            try {

                using FileStream fileStream =
                    new FileStream(
                        filePath,
                        FileMode.Create);

                DataContractJsonSerializer dataContractJsonSerializer =
                    new DataContractJsonSerializer(
                        typeof(T));

                dataContractJsonSerializer.WriteObject(
                    fileStream,
                    dataObject);

            } catch {
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="DataContractJsonSerializer"/> を使用して <see cref="object"/> をデシリアライズします。</para>
        /// </summary>
        public static bool DataContractJsonDeserialize<T>(string filePath, out T dataObject)
        {
            try {

                using FileStream fileStream =
                    new FileStream(
                        filePath,
                        FileMode.Open);

                DataContractJsonSerializer dataContractJsonSerializer =
                    new DataContractJsonSerializer(
                        typeof(T));

                var obj =
                    dataContractJsonSerializer.ReadObject(
                        fileStream);

                dataObject = (T)obj;

            } catch {
                dataObject = default;
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="XamlWriter"/> を使用して <see cref="UIElement"/> をシリアライズします。</para>
        /// </summary>
        public static bool XamlSerialize<T>(string filePath, T uiElement)
        {
            try {

                //string xamlString =
                //    XamlWriter.Save(
                //        uiElement);

                //File.WriteAllText(
                //    filePath,
                //    xamlString);

                using XmlWriter xmlWriter =
                    XmlWriter.Create(
                        filePath,
                        xmlWriterSettings);

                XamlWriter.Save(
                    uiElement,
                    xmlWriter);

            } catch {
                return false;
            }
            return true;
        }

        /// <summary>
        /// <para><see cref="XamlReader"/> を使用して <see cref="UIElement"/> をデシリアライズします。</para>
        /// </summary>
        public static bool XamlDeserialize<T>(string filePath, out T uiElement)
        {
            try {

                //string xamlString =
                //    File.ReadAllText(
                //        filePath);

                //var obj =
                //    XamlReader.Parse(
                //        xamlString);

                //uiElement = (T)obj;

                using XmlReader xmlReader =
                    XmlReader.Create(
                        filePath);

                var obj =
                    XamlReader.Load(
                        xmlReader);

                uiElement = (T)obj;

            } catch {
                uiElement = default;
                return false;
            }
            return true;
        }
    }
}

```

#まとめ
オブジェクトのシリアライズ・デシリアライズには色々ライブラリが出回ってるみたいですけど、最初のとっかかりとしてはやはり標準を使いたい。というわけなので簡単にまとめてみたわけですが...。
今どきWPFでシリアライズの話？もうやり尽くされてますわ。見たいな感じですよね...。（でも、ざっとまとまってるのがなかったから！）

おまけとして。後は、プロパティにつける属性なんかがあったりします。
属性とはなんぞや？　という方は XmlElement とかでｇｇると幸せになれるかもです。

ちなみに初投稿。お目汚し失礼しました('ω')ノ