前面在《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++)

{
string text1 = names[num1 * 4];
SettingsPropertyValue value1 = properties[text1];
if (value1 != null)

{
int num2 = int.Parse(names[(num1 * 4) + 2], CultureInfo.InvariantCulture);
int num3 = int.Parse(names[(num1 * 4) + 3], CultureInfo.InvariantCulture);
if (num3 == -1)

{
if (!value1.Property.PropertyType.IsValueType)

{
value1.PropertyValue = null;
value1.IsDirty = false;
value1.Deserialized = true;
}
}
else

{
if (((names[(num1 * 4) + 1] == "S") && (num2 >= 0)) && ((num3 > 0) && (values.Length >= (num2 + num3))))

{
value1.SerializedValue = values.Substring(num2, num3);
}
if (((names[(num1 * 4) + 1] == "B") && (num2 >= 0)) && ((num3 > 0) && (buf.Length >= (num2 + num3))))

{
byte[] buffer1 = new byte[num3];
Buffer.BlockCopy(buf, num2, buffer1, 0, num3);
value1.SerializedValue = buffer1;
}
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?