ArcObjects SDK對象的序列化和反序列化

在ArcObjects SDK,序列化接口是IPersistStream,該接口的定義如下。

截圖.png

其中GetClassID函數可以獲取實際類型的唯一ID,Load函數是反序列化函數,Save函數爲序列化函數。我們看下Load和Save函數是接收什麼參數。

Save函數的定義如下所示。

public void Save (IStream pstm,int fClearDirty);
public void Load (IStream pstm);

Save函數傳入IStream接口類型的對象,第二個參數是否清空該對象的髒狀態。Load函數也是傳入一個IStream接口類型的對象。IStream的定義如下。

截圖.png

從幫助中看出只有一個XMLStream繼承實現了IStream接口,但實際操作的時候,保存的xml字符串會有亂碼,想把這些字符串分序列化回去的時候,會報錯。這個問題估計是有其他辦法解決,但我一直沒有找到解決辦法,所以此路走不通。

實際上,除了XMLStream外,還有ESRI.ArcGIS.esriSystem.MemoryBlobStreamClass類也繼承IStream接口,但不知道爲什麼幫助裏面沒有體現出來。從MemoryBlobStreamClass的命名也可以看出,使用這個類可以保存成二進制,也就是byte[],然後我們把byte[]轉換成字符串就可以和其他信息一起保存成文件或者xml中的一個節點了。

序列化代碼如下。

public static string ToPersistString(IPersistStream pPersistStream)
{
    if (pPersistStream == null)
    {
        return "";
    }
    //得到ClassGuid
    pPersistStream.GetClassID(out Guid myClassGuid);
    string myClassGUID = myClassGuid.ToString();
    //得到二進制信息
    IMemoryBlobStream myMemoryBlobStream = new MemoryBlobStreamClass();
    pPersistStream.Save(myMemoryBlobStream, 0);
    IMemoryBlobStreamVariant myMemoryBlobStreamVariant = myMemoryBlobStream as IMemoryBlobStreamVariant;
    myMemoryBlobStreamVariant.ExportToVariant(out object myObject);
    return myClassGUID + "," + Convert.ToBase64String(myObject as byte[]);
}

需要注意的是,我們除了得到byte[]之外,還需要得到該對象所屬類的ClassGUID,通過IPersistStream的GetClassID函數可以獲取到,獲取之後,和byte[]一起保存成字符串。只有知道這段信息保存的是哪個類的實例,才能實例化出一個對象,並把該對象轉換成IPersistStream接口,最後調該接口的Load函數加載信息。

反序列化的代碼如下。

public static IPersistStream FromPersistString(string pPersistString)
{
    if (pPersistString.Trim().Length == 0)
    {
        return null;
    }
    string[] myPersistArray = pPersistString.Split(',');
    if (myPersistArray.Length < 1)
    {
        throw new ArgumentException("AoSerializer error.");
    }

    Type myType = Type.GetTypeFromCLSID(new Guid(myPersistArray[0]));
    IPersistStream myPersistStream = Activator.CreateInstance(myType) as IPersistStream;

    byte[] myByteArray = Convert.FromBase64String(myPersistArray[1]);
    IMemoryBlobStream myMemoryBlobStream = new MemoryBlobStreamClass();
    IMemoryBlobStreamVariant myMemoryBlobStreamVariant = myMemoryBlobStream as IMemoryBlobStreamVariant;
    myMemoryBlobStreamVariant.ImportFromVariant(myByteArray);
    myPersistStream.Load(myMemoryBlobStream);
    return myPersistStream;
}

反序列化代碼首先先把ClassGUID和byte[]對應的字符串分類,通過調用Type.GetTypeFromCLSID(new Guid(myPersistArray[0]));函數,可以獲取具體的類型,然後通過Activator.CreateInstance(myType)函數實例化一個該類型的對象,當然該對象肯定是繼承了IPersistStream接口的。

有了對象,有了數據,最後調用 myPersistStream.Load(myMemoryBlobStream);加載數據中的信息,也就是把數據中存儲的信息賦給調用的對象。

一般來說,我會把保存的字符串作爲大xml文件的一個屬性或者節點存儲,如下所示。

截圖.png

在第6行,定義了TextSymbol屬性,該屬性存儲了繼承ITextSymbol接口的對象,至於是哪個類,靠“,”號前面的的GUID字符串去識別,“,”號後面就是存儲的具體數據。

第8行定義了MapSurroundFrame屬性,該屬性下存儲了一個IMapSurroundFrame接口類型的對象,解析方法和TextSymbol一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章