今回は、デシリアライズ後にコールバックメソッドを呼ぶ処理の書き方です。
.Netではデシリアライズ後に特定の処理を行う為の方法が2種類あります。
- IDeserializationCallbackを実装する
- OnSerializedAttributeを利用する
今回は、IDeserializationCallbackインターフェースの実装についてです。
OnSerializedAttributeについては、次回記述します。
IDeserializationCallbackインターフェースには以下のメソッドが一つだけ定義されています。
void OnDeserialization(object sender);
上記のメソッドの引数senderは、msdnには「現状実装されていません。」と記述されています。
実際、常にnullが設定されています。
このメソッドを定義しておくと、デシリアライズが完了した後でコールバックされます。
ただし、IDeserializationCallbackインターフェースを利用する上で一つ注意点があります。
このメソッドは、XmlSerializerでは呼ばれない。
XmlSerializer以外のもの、つまり、BinaryFormatterとSoapFormatterではよばれます。
特に、XmlSerializerを使っているからといってコンパイルエラーが出るわけではないので
注意が必要です。
以下、サンプルです。
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) { // // IDeserializationCallbackを利用した処理. // // IDeserializationCallbackを利用するとデシリアライズ後に // カスタム処理を実行することが出来るようになる. // Console.WriteLine("============ (IDeserializationCallback) ==========="); ExecuteIDeserializationCallback(); Console.WriteLine("Press any key to exit..."); Console.ReadLine(); } #region Helper Methods private static void ExecuteIDeserializationCallback() { // // 元データを構築. // var originalObject = new Data3 { Id = 1, Name = "Name-1" }; // // XmlSerializerを利用してシリアライズ及びデシリアライズ. // コールバックメソッドは呼ばれない。 // using (TextWriter writer = new StreamWriter("Data3-XML.xml", false, Encoding.GetEncoding("sjis"))) { new XmlSerializer(originalObject.GetType()).Serialize(writer, originalObject); } using (TextReader reader = new StreamReader("Data3-XML.xml", Encoding.GetEncoding("sjis"))) { var deserializedObject = new XmlSerializer(originalObject.GetType()).Deserialize(reader); foreach (PropertyInfo propInfo in deserializedObject.GetType().GetProperties()) { Console.WriteLine("{0}={1}", propInfo.Name, propInfo.GetValue(deserializedObject, null)); } } Console.WriteLine(string.Empty); // // BinaryFormatterを利用してシリアライズ及びデシリアライズ. // コールバックメソッドが呼ばれる。 // using (Stream writer = File.Open("Data3-DAT.xml", FileMode.Create)) { new BinaryFormatter().Serialize(writer, originalObject); } using (Stream reader = File.Open("Data3-DAT.xml", FileMode.Open)) { var deserializedObject = new BinaryFormatter().Deserialize(reader); foreach (PropertyInfo propInfo in deserializedObject.GetType().GetProperties()) { Console.WriteLine("{0}={1}", propInfo.Name, propInfo.GetValue(deserializedObject, null)); } } Console.WriteLine(string.Empty); // // SoapFormatterを利用してシリアライズ及びデシリアライズ. // コールバックメソッドが呼ばれる。 // using (Stream writer = File.Open("Data3-SOAP.xml", FileMode.Create)) { new SoapFormatter().Serialize(writer, originalObject); } using (Stream reader = File.Open("Data3-SOAP.xml", FileMode.Open)) { var deserializedObject = new SoapFormatter().Deserialize(reader); foreach (PropertyInfo propInfo in deserializedObject.GetType().GetProperties()) { Console.WriteLine("{0}={1}", propInfo.Name, propInfo.GetValue(deserializedObject, null)); } } } #endregion } #region Sample Classes // // System.Runtime.Selialization.IDeserializationCallbackインターフェースを // 実装している型。 // // OnDeserializationメソッドは、デシリアライズが完了した後に呼ばれる。 // // 尚、OnDeserializationメソッドは、何故かXmlSerializer経由だと呼ばれない。 // BinaryFormatterなどのフォーマッター経由だと呼び出される。 // // どうもIDeserializationCallbackはruntime serializerの場合しか動作しないようである。 // (ex: BinaryFomatter, SoapFormatter) // XmlSerializerは、そうではないので動かないらしい。 // // -- http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-xml/471/IDeserializationCallback-and-XmlSerializer // // The IDeserializationCallback is only used by the runtime serializers, i.e. // the SoapFormatter and the BinaryFormatter. There isn't really any counter // part for the XmlSerializer. // [Serializable] public class Data3 : IDeserializationCallback { public int Id { get; set; } public string Name { get; set; } /// <summary> /// オブジェクトがデシリアライズされた後にコールバックされます。 /// </summary> /// <param name="sender">現在実装されていないとの事 (by msdn)。必ずnullが設定されている。</param> void IDeserializationCallback.OnDeserialization(object sender) { // // わざと値を変更する. // Id += 100; Name = "Modified"; } } #endregion }
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場