Persist


ArcObjectsのシリアライズをラッピング
ArcObjectsは、バイナリ化用にIPersistStreamを持っているのでMXDファイル等
byte配列のバイナリファイルを生成できる。
MXDに保存されている情報は(レンダラ/シンボル/データソースなど)はバイナリ化可能。

とりあえずラッピングすれば、通常の.NETのシリアライズ機構に乗っかれる。

using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using sys = System.IO;
using (ComReleaser com = new ComReleaser())
{
  IEnvelope env = new EnvelopeClass();
  com.ManageLifetime(env);
  env.PutCoords(120, 20, 150, 50);

  EsriSerializable<IEnvelope> envNet = new EsriSerializable<IEnvelope>(env);

  using (sys.FileStream fs = new sys.FileStream(@"C:\TEST.env", sys.FileMode.Create, sys.FileAccess.Write))
  {
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs, envNet);
    fs.Close();
  }
  //強制解放
  Marshal.FinalReleaseComObject(env);

  try
  {
    //これはエラーになるはず
    Debug.Print("{0} {1} {2} {3}", envNet.Data.XMin, envNet.Data.YMin, envNet.Data.XMax, envNet.Data.YMax);
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
  }

  using (sys.FileStream fs = new sys.FileStream(@"C:\TEST.env", sys.FileMode.Open, sys.FileAccess.Read))
  {
    BinaryFormatter f = new BinaryFormatter();
    envNet = (EsriSerializable<IEnvelope>)f.Deserialize(fs);
    fs.Close();
  }

  com.ManageLifetime(envNet.Data);
  Debug.Print("{0} {1} {2} {3}", envNet.Data.XMin, envNet.Data.YMin, envNet.Data.XMax, envNet.Data.YMax);
}
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.esriSystem;
using System;
using System.Runtime.Serialization;


[Serializable()]
public class EsriSerializable<T> : ISerializable
{
  private const string DATA_NAME = "DATA_NAME";
  private const string PROG_NAME = "PROG_NAME";

  private string m_ProgName = null;
  private object m_obj = null;

  public T Data
  {
    get { return (T)this.m_obj; }
  }

  public EsriSerializable(T comObj)
  {
    if (!(comObj is IClassID) || !(comObj is IPersistStream))
      throw new ArgumentException("IClassID/IPersistStreamインタフェースを実装している必要があります。");

    this.m_ProgName = ((IClassID)comObj).GetProgID();
    this.m_obj = comObj;
  }

  protected EsriSerializable(SerializationInfo info, StreamingContext context)
  {

    byte[] data = (byte[])info.GetValue(DATA_NAME, typeof(byte[]));
    string prgId = info.GetString(PROG_NAME);

    using (ComReleaser com = new ComReleaser())
    {
      IMemoryBlobStream memStream = new MemoryBlobStreamClass();
      com.ManageLifetime(memStream);

      IMemoryBlobStreamVariant variant = (IMemoryBlobStreamVariant)memStream;

      variant.ImportFromVariant((object)data);

      IObjectStream anObjectStream = new ObjectStreamClass();
      com.ManageLifetime(anObjectStream);
      anObjectStream.Stream = memStream;

      Type t = Type.GetTypeFromProgID(prgId);
      IPersistStream perStream = Activator.CreateInstance(t) as IPersistStream;
      perStream.Load(anObjectStream);

      this.m_obj = (object)perStream;
    }//end com

  }

  public void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    var comObj = this.m_obj;

    using (ComReleaser com = new ComReleaser())
    {
      IPersistStream perStream = comObj as IPersistStream;

      IObjectStream objStream = new ObjectStreamClass();
      com.ManageLifetime(objStream);
      IMemoryBlobStream memStream = new MemoryBlobStreamClass();
      com.ManageLifetime(memStream);

      objStream.Stream = memStream;
      perStream.Save(objStream, 0);

      IMemoryBlobStreamVariant variant = (IMemoryBlobStreamVariant)memStream;

      Object expObj = null;
      variant.ExportToVariant(out expObj);

      var data = (byte[])expObj;
      info.AddValue(DATA_NAME, data);
      info.AddValue(PROG_NAME, this.m_ProgName);

    }//end com
  }//end method
}//end class
カテゴリー: 開発 タグ: パーマリンク