読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

.NET クラスライブラリ探訪-029 (シリアライズ-2)(NonSerialized, XmlIgnore)

C#


今回は、シリアライズの際に特定のフィールドまたはプロパティをシリアライズ対象から外す事についてです。


前回で、シリアライズの基本的な方法はわかりました。
しかし、実際には全ての値をシリアライズしたくない場面もあります。


計算にて求めるフィールドまたはプロパティなどは、よくあるパターンですね。


その場合、以下の属性を利用します。

  • NonSerializedAttribute
    • XmlSerializer以外のSelializerを利用している場合に利用します。
  • XmlIgnoreAttribute
    • XmlSerializerを利用している場合に利用します。


NonSerializedAttributeは、フィールドに、XmlIgnoreAttributeはプロパティに付与します。
注意点として、それぞれ特定のSerializerに対して効果を発揮します。


XmlSerializerを利用している場合、NonSerializedAttributeを指定していても
無視され、値がシリアライズされてしまいます。


以下、サンプルです。

using System;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace SerializationSample
{
    class Program
    {
        static void Main(string[] args)
        {
            //
            // NonSerialized, XmlIgnoreを利用して特定のフィールドをシリアライズしないように処理.
            //
            Console.WriteLine("============ (NonSerialized) ===========");

            var data2 = new Data2
                {
                    Id = 1,
                    Name = "Name-1",
                    NonSerializedField = "value"
                };

            WriteXmlSerializedData("Data2-XML.xml", data2);
            PrintDeserializedData(typeof(Data2), "Data2-XML.xml");

            WriteBinarySerializedData("Data2-DAT.xml", data2);
            PrintBinaryDeserializedData(typeof(Data2), "Data2-DAT.xml");

            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }

        #region Helper Methods
        private static void WriteXmlSerializedData(string filePath, object data)
        {
            if (data == null)
            {
                return;
            }

            using (TextWriter writer = new StreamWriter(filePath, false, Encoding.GetEncoding("sjis")))
            {
                (new XmlSerializer(data.GetType())).Serialize(writer, data);
                Console.WriteLine(string.Empty);
            }
        }

        private static void WriteBinarySerializedData(string filePath, object data)
        {
            if (data == null)
            {
                return;
            }
            
            using (Stream writer = File.Open(filePath, FileMode.Create))
            {
                (new BinaryFormatter()).Serialize(writer, data);
                Console.WriteLine(string.Empty);
            }
        }

        private static void PrintDeserializedData(Type type, string filePath)
        {
            using (XmlReader reader = XmlReader.Create(filePath))
            {
                var data = new XmlSerializer(type).Deserialize(reader);
                foreach (PropertyInfo propInfo in data.GetType().GetProperties())
                {
                    Console.WriteLine("{0}={1}", propInfo.Name, propInfo.GetValue(data, null));
                }
            }
        }

        private static void PrintBinaryDeserializedData(Type type, string filePath)
        {
            using (Stream reader = File.Open(filePath, FileMode.Open))
            {
                var data = new BinaryFormatter().Deserialize(reader);
                foreach (PropertyInfo propInfo in data.GetType().GetProperties())
                {
                    Console.WriteLine("{0}={1}", propInfo.Name, propInfo.GetValue(data, null));
                }
            }

        }
        #endregion
    }

    #region Sample Classes
    [Serializable]
    public class Data2
    {
        public int Id
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        //
        // Runtime Serializer (ex: BinaryFormatter)を利用する場合は
        // フィールドに対して、NonSerializedを付与する。
        //
        [NonSerialized]
        private string _nonSerializedField;

        //
        // XmlSerializerを利用する場合は、プロパティに対してXmlIgnoreを付与する。
        //
        [XmlIgnore]
        public string NonSerializedField
        {
            get
            {
                return _nonSerializedField;
            }
            set
            {
                _nonSerializedField = value;
            }
        }
        
    }
    #endregion
}

================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。