ArcObjects SDK开发 025 AO中对象的序列化和反序列化

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

ArcObjects SDK开发 025 AO中对象的序列化和反序列化

其中GetClassID函数可以获取实际类型的唯一ID,Load函数是反序列化函数,Save函数为序列化函数。我们看下Load和Save函数是接收什么参数。

Save函数的定义如下所示。

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

Save函数传入IStream接口类型的对象,第二个参数是否清空该对象的脏状态。Load函数也是传入一个IStream接口类型的对象。IStream的定义如下。

ArcObjects SDK开发 025 AO中对象的序列化和反序列化

从帮助中看出只有一个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文件的一个属性或者节点存储,如下所示。

ArcObjects SDK开发 025 AO中对象的序列化和反序列化

在第6行,定义了TextSymbol属性,该属性存储了继承ITextSymbol接口的对象,至于是哪个类,靠“,”号前面的的GUID字符串去识别,“,”号后面就是存储的具体数据。

第8行定义了MapSurroundFrame属性,该属性下存储了一个IMapSurroundFrame接口类型的对象,解析方法和TextSymbol一样。

发表评论

相关文章