日期:2009-07-28  浏览次数:20483 次

前面在《ASP.Net Forums中对.Net中序列化和反序列化的应用》一文中讲了,对于一些扩展属性,可以将字符串集合序列化为二进制,也可以从二进制反序列化为字符串集合。其实我一直有个疑问,对于ASP.net中可以很容易实现,但是在ASP中该如何?

在CS和DNN3中都采用了ASP.net2.0的新特性MemberShip,今天研究了一下CSBeta2,特地研究了一下MemberShip中对于用户资料的序列化保存。发现在ASPnet_Profile表中有三个特殊字段PropertyNames、PropertyValuesString和PropertyValuesBinary,其中的PropertyValuesBinary十之八九就是保存序列化为二进制后的内容。对于PropertyNames、PropertyValuesString这两个字段倒是不知道,打开查看,发现其中一条记录这两个字段的内容分别为下面两行的内容:

publicEmail:S:0:0:yahooIM:S:0:0:timezone:S:0:1:birthdate:B:0:-1:gender:S:1:6:location:S:7:0:fontsize:S:7:1:signature:S:8:0:dateFormat:S:8:10:webLog:S:18:7:enablePostPreviewPopup:B:0:-1:language:S:25:5:interests:S:30:0:occupation:S:30:0:webAddress:S:30:7:icqIM:S:37:0:aolIM:S:37:0:signatureFormatted:S:37:0:msnIM:S:37:0:


8NotSet0MM-dd-yyyyhttp://zh-CNhttp://

借助Reflector分析了一下源码,终于明白了,原来在PropertyNames字段中,由“:”分割为若干个数组,其中每个属性占数组的4项(如publicEmail:S:0:0:为一个属性的整体):
第1项为属性名称
第2项有两种可能值,B表示该属性值为null,S表示不为null
第3项表示在PropertyValuesString字段中字符串的起始位置
第4项表示长度
那么publicEmail:S:0:0:就表示为空值,timezone:S:0:1:表示“8NotSet0MM-dd-yyyyhttp://zh-CNhttp://“中从0开始取1个字符长度为“8”,birthdate:B:0:-1:就表示为null,dateFormat:S:8:10:就表示取“8NotSet0MM-dd-yyyyhttp://zh-CNhttp://”中第8位开始取10个字符为“MM-dd-yyyy”……

通过这种序列化为字符串的方式,即使是一些弱语言,如vbscript,jscript都可以实现序列化和反序列化了,那么在ASP中也就可以共享ASP.net的MemberShip了。

贴两段核心代码参考一下:

internal static void PrepareDataForSaving(ref string allNames, ref string allValues, ref byte[] buf, bool binarySupported, SettingsPropertyValueCollection properties, bool userIsAuthenticated) 

      StringBuilder builder1 = new StringBuilder(); 
      StringBuilder builder2 = new StringBuilder(); 
      MemoryStream stream1 = binarySupported ? new MemoryStream() : null; 
      try 
      { 
            bool flag1 = false; 
            foreach (SettingsPropertyValue value1 in properties) 
            { 
                  if (!value1.IsDirty) 
                  { 
                        continue; 
                  } 
                  if (userIsAuthenticated || ((bool) value1.Property.Attributes["AllowAnonymous"])) 
                  { 
                        flag1 = true; 
                        break; 
                  } 
      &nb