摘要:前面在《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; } } if (!flag1) { return; } foreach (SettingsPropertyValue value2 in properties) { if (!userIsAuthenticated && !((bool) value2.Property.Attributes["AllowAnonymous"])) { continue; } if (value2.IsDirty || !value2.UsingDefaultValue) { int num1 = 0; int num2 = 0; string text1 = null; if (value2.Deserialized && (value2.PropertyValue == null)) { num1 = -1; } else { object obj1 = value2.SerializedValue; if (obj1 == null) { num1 = -1; } else { if (!(obj1 is string) && !binarySupported) { obj1 = Convert.ToBase64String((byte[]) obj1); } if (obj1 is string) { text1 = (string) obj1; num1 = text1.Length; num2 = builder2.Length; } else { byte[] buffer1 = (byte[]) obj1; num2 = (int) stream1.Position; stream1.Write(buffer1, 0, buffer1.Length); stream1.Position = num2 + buffer1.Length; num1 = buffer1.Length; } } } string[] textArray1 = new string[8] { value2.Name, ":", (text1 != null) ? "S" : "B", ":", num2.ToString(CultureInfo.InvariantCulture), ":", num1.ToString(CultureInfo.InvariantCulture), ":" } ; builder1.Append(string.Concat(textArray1)); if (text1 != null) { builder2.Append(text1); } } } if (binarySupported) { buf = stream1.ToArray(); } } catch { throw; } finally { if (stream1 != null) { stream1.Close(); } } allNames = builder1.ToString(); allValues = builder2.ToString(); } internal static void ParseDataFromDB(string[] names, string values, byte[] buf, SettingsPropertyValueCollection properties) { for (int num1 = 0; num1 < (names.Length / 4); num1++) {......[
阅读全文]