C# 版本的 PHP serialize/unserialize 完整实现

原创作品,转载请注明出处。

这个版本目前实现了对各种基元类型、一维数组、多维数组、交错数组、ArrayList、Hashtable、和其它可序列化对象的序列化。实现了 PHP 5 中的 Serializable 接口的支持。实现了 PHP 中的 __sleep 和 __wakeup 魔术方法的支持。实现了对所有标示(N、b、i、d、s、a、O、R、r、U、C)的反序列化,在对标示 a 反序列化时,可以根据下标和值来自动判断是 ArrayList 还是 Hashtable。并且在反序列化时可以强制指定反序列化的类型。

该类是静态类,无需也不能被实例化。除了包含了 Serialize 和 UnSerialize 方法以外,还增加了一个 ChangeType 方法,用来进行反序列化后的类型转换,该方法比 Convert.ChangeType 方法的转换的能力更强。

实现代码

PHPSerializer.cs
  1. /* PHPSerializer.cs
  2. *
  3. * Author:       Ma Bingyao <andot@ujn.edu.cn>
  4. * Copyright:    CoolCode.CN
  5. * Version:      3.7
  6. * LastModified: 2007-02-09
  7. * This library is free.  You can redistribute it and/or modify it.
  8. * http://www.coolcode.cn/?p=193
  9. */
  10.  
  11. using System;
  12. using System.IO;
  13. using System.Collections;
  14. using System.Text;
  15. using System.Reflection;
  16.  
  17. public interface Serializable
  18. {
  19.     byte[] Serialize();
  20.     void UnSerialize(byte[] ss);
  21. }
  22. public class UnSerializeException : Exception
  23. {
  24.     public UnSerializeException() { }
  25.     public UnSerializeException(string message) : base(message) { }
  26.     public UnSerializeException(string message, Exception inner) : base(message, inner) { }
  27. }
  28. public class PHPSerializer
  29. {
  30.     private static Hashtable __ns;
  31.     private const byte __Quote = 34;
  32.     private const byte __0 = 48;
  33.     private const byte __1 = 49;
  34.     private const byte __Colon = 58;
  35.     private const byte __Semicolon = 59;
  36.     private const byte __C = 67;
  37.     private const byte __N = 78;
  38.     private const byte __O = 79;
  39.     private const byte __R = 82;
  40.     private const byte __U = 85;
  41.     private const byte __Slash = 92;
  42.     private const byte __a = 97;
  43.     private const byte __b = 98;
  44.     private const byte __d = 100;
  45.     private const byte __i = 105;
  46.     private const byte __r = 114;
  47.     private const byte __s = 115;
  48.     private const byte __LeftB = 123;
  49.     private const byte __RightB = 125;
  50.     static PHPSerializer()
  51.     {
  52.         __ns = new Hashtable();
  53.         Assembly[] assem = AppDomain.CurrentDomain.GetAssemblies();
  54.         for (int i = 0; i < assem.Length; i++)
  55.         {
  56.             Module[] m = assem[i].GetModules();
  57.             for (int j = 0; j < m.Length; j++)
  58.             {
  59.                 try
  60.                 {
  61.                     Type[] t = m[j].GetTypes();
  62.                     for (int k = 0; k < t.Length; k++)
  63.                     {
  64.                         if (t[k].Namespace != null && !__ns.ContainsKey(t[k].Namespace))
  65.                         {
  66.                             __ns[t[k].Namespace] = assem[i].FullName;
  67.                         }
  68.                     }
  69.                 }
  70.                 catch
  71.                 {
  72.                 }
  73.             }
  74.         }
  75.     }
  76.     private PHPSerializer()
  77.     {
  78.     }
  79.     public static byte[] Serialize(object obj)
  80.     {
  81.         return Serialize(obj, Encoding.UTF8);
  82.     }
  83.     public static byte[] Serialize(object obj, Encoding encoding)
  84.     {
  85.         Hashtable ht = new Hashtable();
  86.         int hv = 1;
  87.         MemoryStream stream = new MemoryStream();
  88.         stream.Seek(0, SeekOrigin.Begin);
  89.         Serialize(stream, obj, ht, ref hv, encoding);
  90.         byte[] result = stream.ToArray();
  91.         stream.Close();
  92.         return result;
  93.     }
  94.     private static void Serialize(MemoryStream stream, object obj, Hashtable ht, ref int hv, Encoding encoding)
  95.     {
  96.         if (obj == null)
  97.         {
  98.             hv++;
  99.             WriteNull(stream);
  100.         }
  101.         else if (obj is Boolean)
  102.         {
  103.             hv++;
  104.             WriteBoolean(stream, ((Boolean)obj) ? __1 : __0);
  105.         }
  106.         else if ((obj is Byte) || (obj is SByte) || (obj is Int16) || (obj is UInt16) || (obj is Int32))
  107.         {
  108.             hv++;
  109.             WriteInteger(stream, Encoding.ASCII.GetBytes(obj.ToString()));
  110.         }
  111.         else if ((obj is UInt32) || (obj is Int64) || (obj is UInt64) || (obj is Decimal))
  112.         {
  113.             hv++;
  114.             WriteDouble(stream, Encoding.ASCII.GetBytes(obj.ToString()));
  115.         }
  116.         else if (obj is Single)
  117.         {
  118.             hv++;
  119.             if (Single.IsNaN((Single)obj))
  120.             {
  121.                 WriteDouble(stream, Encoding.ASCII.GetBytes("NAN"));
  122.             }
  123.             else if (Single.IsPositiveInfinity((Single)obj))
  124.             {
  125.                 WriteDouble(stream, Encoding.ASCII.GetBytes("INF"));
  126.             }
  127.             else if (Single.IsNegativeInfinity((Single)obj))
  128.             {
  129.                 WriteDouble(stream, Encoding.ASCII.GetBytes("-INF"));
  130.             }
  131.             else
  132.             {
  133.                 WriteDouble(stream, Encoding.ASCII.GetBytes(obj.ToString()));
  134.             }
  135.         }
  136.         else if (obj is Double)
  137.         {
  138.             hv++;
  139.             if (Double.IsNaN((Double)obj))
  140.             {
  141.                 WriteDouble(stream, Encoding.ASCII.GetBytes("NAN"));
  142.             }
  143.             else if (Double.IsPositiveInfinity((Double)obj))
  144.             {
  145.                 WriteDouble(stream, Encoding.ASCII.GetBytes("INF"));
  146.             }
  147.             else if (Double.IsNegativeInfinity((Double)obj))
  148.             {
  149.                 WriteDouble(stream, Encoding.ASCII.GetBytes("-INF"));
  150.             }
  151.             else
  152.             {
  153.                 WriteDouble(stream, Encoding.ASCII.GetBytes(obj.ToString()));
  154.             }
  155.         }
  156.         else if ((obj is Char) || (obj is String))
  157.         {
  158.             hv++;
  159.             WriteString(stream, encoding.GetBytes(obj.ToString()));
  160.         }
  161.         else if (obj is Array)
  162.         {
  163.             if (ht.ContainsKey(obj.GetHashCode()))
  164.             {
  165.                 WritePointRef(stream, Encoding.ASCII.GetBytes(ht[obj.GetHashCode()].ToString()));
  166.             }
  167.             else
  168.             {
  169.                 ht.Add(obj.GetHashCode(), hv++);
  170.                 WriteArray(stream, obj as Array, ht, ref hv, encoding);
  171.             }
  172.         }
  173.         else if (obj is ArrayList)
  174.         {
  175.             if (ht.ContainsKey(obj.GetHashCode()))
  176.             {
  177.                 WritePointRef(stream, Encoding.ASCII.GetBytes(ht[obj.GetHashCode()].ToString()));
  178.             }
  179.             else
  180.             {
  181.                 ht.Add(obj.GetHashCode(), hv++);
  182.                 WriteArrayList(stream, obj as ArrayList, ht, ref hv, encoding);
  183.             }
  184.         }
  185.         else if (obj is Hashtable)
  186.         {
  187.             if (ht.ContainsKey(obj.GetHashCode()))
  188.             {
  189.                 WritePointRef(stream, Encoding.ASCII.GetBytes(ht[obj.GetHashCode()].ToString()));
  190.             }
  191.             else
  192.             {
  193.                 ht.Add(obj.GetHashCode(), hv++);
  194.                 WriteHashtable(stream, obj as Hashtable, ht, ref hv, encoding);
  195.             }
  196.         }
  197.         else
  198.         {
  199.             if (ht.ContainsKey(obj.GetHashCode()))
  200.             {
  201.                 hv++;
  202.                 WriteRef(stream, Encoding.ASCII.GetBytes(ht[obj.GetHashCode()].ToString()));
  203.             }
  204.             else
  205.             {
  206.                 ht.Add(obj.GetHashCode(), hv++);
  207.                 WriteObject(stream, obj, ht, ref hv, encoding);
  208.             }
  209.         }
  210.     }
  211.     private static void WriteNull(MemoryStream stream)
  212.     {
  213.         stream.WriteByte(__N);
  214.         stream.WriteByte(__Semicolon);
  215.     }
  216.     private static void WriteRef(MemoryStream stream, byte[] r)
  217.     {
  218.         stream.WriteByte(__r);
  219.         stream.WriteByte(__Colon);
  220.         stream.Write(r, 0, r.Length);
  221.         stream.WriteByte(__Semicolon);
  222.     }
  223.     private static void WritePointRef(MemoryStream stream, byte[] p)
  224.     {
  225.         stream.WriteByte(__R);
  226.         stream.WriteByte(__Colon);
  227.         stream.Write(p, 0, p.Length);
  228.         stream.WriteByte(__Semicolon);
  229.     }
  230.     private static void WriteBoolean(MemoryStream stream, byte b)
  231.     {
  232.         stream.WriteByte(__b);
  233.         stream.WriteByte(__Colon);
  234.         stream.WriteByte(b);
  235.         stream.WriteByte(__Semicolon);
  236.     }
  237.     private static void WriteInteger(MemoryStream stream, byte[] i)
  238.     {
  239.         stream.WriteByte(__i);
  240.         stream.WriteByte(__Colon);
  241.         stream.Write(i, 0, i.Length);
  242.         stream.WriteByte(__Semicolon);
  243.     }
  244.     private static void WriteDouble(MemoryStream stream, byte[] d)
  245.     {
  246.         stream.WriteByte(__d);
  247.         stream.WriteByte(__Colon);
  248.         stream.Write(d, 0, d.Length);
  249.         stream.WriteByte(__Semicolon);
  250.     }
  251.     private static void WriteString(MemoryStream stream, byte[] s)
  252.     {
  253.         byte[] slen = Encoding.ASCII.GetBytes(s.Length.ToString());
  254.         stream.WriteByte(__s);
  255.         stream.WriteByte(__Colon);
  256.         stream.Write(slen, 0, slen.Length);
  257.         stream.WriteByte(__Colon);
  258.         stream.WriteByte(__Quote);
  259.         stream.Write(s, 0, s.Length);
  260.         stream.WriteByte(__Quote);
  261.         stream.WriteByte(__Semicolon);
  262.     }
  263.     private static void WriteArray(MemoryStream stream, Array a, Hashtable ht, ref int hv, Encoding encoding)
  264.     {
  265.         if (a.Rank == 1)
  266.         {
  267.             int len = a.GetLength(0);
  268.             byte[] alen = Encoding.ASCII.GetBytes(len.ToString());
  269.             int lb = a.GetLowerBound(0);
  270.             int ub = a.GetUpperBound(0);
  271.             stream.WriteByte(__a);
  272.             stream.WriteByte(__Colon);
  273.             stream.Write(alen, 0, alen.Length);
  274.             stream.WriteByte(__Colon);
  275.             stream.WriteByte(__LeftB);
  276.             for (int i = lb; i <= ub; i++)
  277.             {
  278.                 WriteInteger(stream, Encoding.ASCII.GetBytes(i.ToString()));
  279.                 Serialize(stream, a.GetValue(i), ht, ref hv, encoding);
  280.             }
  281.             stream.WriteByte(__RightB);
  282.         }
  283.         else
  284.         {
  285.             WriteArray(stream, a, new int[] { 0 }, ht, ref hv, encoding);
  286.         }
  287.     }
  288.     private static void WriteArray(MemoryStream stream, Array a, int[] indices, Hashtable ht, ref int hv, Encoding encoding)
  289.     {
  290.         int n = indices.Length;
  291.         int dimension = n - 1;
  292.         int[] temp = new int[n + 1];
  293.         indices.CopyTo(temp, 0);
  294.         int len = a.GetLength(dimension);
  295.         byte[] alen = Encoding.ASCII.GetBytes(len.ToString());
  296.         int lb = a.GetLowerBound(dimension);
  297.         int ub = a.GetUpperBound(dimension);
  298.         stream.WriteByte(__a);
  299.         stream.WriteByte(__Colon);
  300.         stream.Write(alen, 0, alen.Length);
  301.         stream.WriteByte(__Colon);
  302.         stream.WriteByte(__LeftB);
  303.         for (int i = lb; i <= ub; i++)
  304.         {
  305.             WriteInteger(stream, Encoding.ASCII.GetBytes(i.ToString()));
  306.             if (a.Rank == n)
  307.             {
  308.                 indices[n - 1] = i;
  309.                 Serialize(stream, a.GetValue(indices), ht, ref hv, encoding);
  310.             }
  311.             else
  312.             {
  313.                 temp[n - 1] = i;
  314.                 WriteArray(stream, a, temp, ht, ref hv, encoding);
  315.             }
  316.         }
  317.         stream.WriteByte(__RightB);
  318.     }
  319.     private static void WriteArrayList(MemoryStream stream, ArrayList a, Hashtable ht, ref int hv, Encoding encoding)
  320.     {
  321.         int len = a.Count;
  322.         byte[] alen = Encoding.ASCII.GetBytes(len.ToString());
  323.         stream.WriteByte(__a);
  324.         stream.WriteByte(__Colon);
  325.         stream.Write(alen, 0, alen.Length);
  326.         stream.WriteByte(__Colon);
  327.         stream.WriteByte(__LeftB);
  328.         for (int i = 0; i < len; i++)
  329.         {
  330.             WriteInteger(stream, Encoding.ASCII.GetBytes(i.ToString()));
  331.             Serialize(stream, a[i], ht, ref hv, encoding);
  332.         }
  333.         stream.WriteByte(__RightB);
  334.     }
  335.     private static void WriteHashtable(MemoryStream stream, Hashtable h, Hashtable ht, ref int hv, Encoding encoding)
  336.     {
  337.         int len = h.Count;
  338.         byte[] hlen = Encoding.ASCII.GetBytes(len.ToString());
  339.         stream.WriteByte(__a);
  340.         stream.WriteByte(__Colon);
  341.         stream.Write(hlen, 0, hlen.Length);
  342.         stream.WriteByte(__Colon);
  343.         stream.WriteByte(__LeftB);
  344.         foreach (DictionaryEntry entry in h)
  345.         {
  346.             if ((entry.Key is Byte) || (entry.Key is SByte) || (entry.Key is Int16) || (entry.Key is UInt16) || (entry.Key is Int32))
  347.             {
  348.                 WriteInteger(stream, Encoding.ASCII.GetBytes(entry.Key.ToString()));
  349.             }
  350.             else if (entry.Key is Boolean)
  351.             {
  352.                 WriteInteger(stream, new byte[] { ((Boolean)entry.Key) ? __1 : __0 });
  353.             }
  354.             else
  355.             {
  356.                 WriteString(stream, encoding.GetBytes(entry.Key.ToString()));
  357.             }
  358.             Serialize(stream, entry.Value, ht, ref hv, encoding);
  359.         }
  360.         stream.WriteByte(__RightB);
  361.     }
  362.     private static void WriteObject(MemoryStream stream, object obj, Hashtable ht, ref int hv, Encoding encoding)
  363.     {
  364.         Type type = obj.GetType();
  365.         if (type.IsSerializable)
  366.         {
  367.             byte[] typename = encoding.GetBytes(type.Name);
  368.             byte[] typenamelen = Encoding.ASCII.GetBytes(typename.Length.ToString());
  369.             if (obj is Serializable)
  370.             {
  371.                 byte[] cs = ((Serializable)obj).Serialize();
  372.                 byte[] cslen = Encoding.ASCII.GetBytes(cs.Length.ToString());
  373.                 stream.WriteByte(__C);
  374.                 stream.WriteByte(__Colon);
  375.                 stream.Write(typenamelen, 0, typenamelen.Length);
  376.                 stream.WriteByte(__Colon);
  377.                 stream.WriteByte(__Quote);
  378.                 stream.Write(typename, 0, typename.Length);
  379.                 stream.WriteByte(__Quote);
  380.                 stream.WriteByte(__Colon);
  381.                 stream.Write(cslen, 0, cslen.Length);
  382.                 stream.WriteByte(__Colon);
  383.                 stream.WriteByte(__LeftB);
  384.                 stream.Write(cs, 0, cs.Length);
  385.                 stream.WriteByte(__RightB);
  386.             }
  387.             else
  388.             {
  389.                 MethodInfo __sleep = null;
  390.                 try
  391.                 {
  392.                     __sleep = type.GetMethod("__sleep", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase, null, new Type[0], new ParameterModifier[0]);
  393.                 }
  394.                 catch { }
  395.                 int fl = 0;
  396.                 FieldInfo[] f;
  397.                 if (__sleep != null)
  398.                 {
  399.                     string[] fns = (string[])__sleep.Invoke(obj, null);
  400.                     f = new FieldInfo[fns.Length];
  401.                     for (int i = 0, len = f.Length; i < len; i++)
  402.                     {
  403.                         f[i] = type.GetField(fns[i], BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  404.                     }
  405.                 }
  406.                 else
  407.                 {
  408.                     f = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  409.                 }
  410.                 for (int i = 0, len = f.Length; i < len; i++)
  411.                 {
  412.                     if (f[i] != null && !(f[i].IsNotSerialized || f[i].IsInitOnly || f[i].IsLiteral))
  413.                     {
  414.                         fl++;
  415.                     }
  416.                 }
  417.                 byte[] flen = Encoding.ASCII.GetBytes(fl.ToString());
  418.                 stream.WriteByte(__O);
  419.                 stream.WriteByte(__Colon);
  420.                 stream.Write(typenamelen, 0, typenamelen.Length);
  421.                 stream.WriteByte(__Colon);
  422.                 stream.WriteByte(__Quote);
  423.                 stream.Write(typename, 0, typename.Length);
  424.                 stream.WriteByte(__Quote);
  425.                 stream.WriteByte(__Colon);
  426.                 stream.Write(flen, 0, flen.Length);
  427.                 stream.WriteByte(__Colon);
  428.                 stream.WriteByte(__LeftB);
  429.                 for (int i = 0, len = f.Length; i < len; i++)
  430.                 {
  431.                     if (f[i] != null && !(f[i].IsNotSerialized || f[i].IsInitOnly || f[i].IsLiteral))
  432.                     {
  433.                         if (f[i].IsPublic)
  434.                         {
  435.                             WriteString(stream, encoding.GetBytes(f[i].Name));
  436.                         }
  437.                         else if (f[i].IsPrivate)
  438.                         {
  439.                             WriteString(stream, encoding.GetBytes("\0" + f[i].DeclaringType.Name + "\0" + f[i].Name));
  440.                         }
  441.                         else
  442.                         {
  443.                             WriteString(stream, encoding.GetBytes("\0*\0" + f[i].Name));
  444.                         }
  445.                         Serialize(stream, f[i].GetValue(obj), ht, ref hv, encoding);
  446.                     }
  447.                 }
  448.                 stream.WriteByte(__RightB);
  449.             }
  450.         }
  451.         else
  452.         {
  453.             WriteNull(stream);
  454.         }
  455.     }
  456.     public static object ChangeType(object obj, Type destType)
  457.     {
  458.         if (obj == null)
  459.         {
  460.             return null;
  461.         }
  462.  
  463.         Type sourceType = obj.GetType();
  464.  
  465.         if (sourceType == destType)
  466.         {
  467.             return obj;
  468.         }
  469.  
  470.         if (obj is ArrayList && destType.IsArray)
  471.         {
  472.             return ArrayListToArray(obj as ArrayList, destType.GetArrayRank(), destType.GetElementType());
  473.         }
  474.         else if (obj is ArrayList && destType == typeof(Hashtable))
  475.         {
  476.             return ArrayListToHashtable(obj as ArrayList);
  477.         }
  478.         else if ((!sourceType.IsByRef && destType.IsByRef) || (!sourceType.IsPointer && destType.IsPointer))
  479.         {
  480.             return Convert.ChangeType(obj, destType.GetElementType());
  481.         }
  482.         else
  483.         {
  484.             return Convert.ChangeType(obj, destType);
  485.         }
  486.     }
  487.     private static Hashtable ArrayListToHashtable(ArrayList a)
  488.     {
  489.         int n = a.Count;
  490.         Hashtable h = new Hashtable(n);
  491.         for (int i = 0; i < n; i++)
  492.         {
  493.             h[i] = a[i];
  494.         }
  495.         return h;
  496.     }
  497.     private static Array ArrayListToArray(ArrayList obj, int rank, Type elementType)
  498.     {
  499.         int[] lengths = new int[rank];
  500.         ArrayList al = obj;
  501.         for (int i = 0; i < rank; i++)
  502.         {
  503.             lengths[i] = al.Count;
  504.             if (al.Count > 0)
  505.             {
  506.                 al = al[0] as ArrayList;
  507.             }
  508.             else
  509.             {
  510.                 break;
  511.             }
  512.         }
  513.         Array result = Array.CreateInstance(elementType, lengths);
  514.         if (lengths[0] > 0)
  515.         {
  516.             ArrayListToArray(obj as ArrayList, result, new int[] { 0 }, elementType);
  517.         }
  518.         return result;
  519.     }
  520.     private static void ArrayListToArray(ArrayList source, Array dest, int[] indices, Type elementType)
  521.     {
  522.         int n = indices.Length;
  523.         int dimension = n - 1;
  524.         int[] temp = new int[n + 1];
  525.         indices.CopyTo(temp, 0);
  526.         int len = dest.GetLength(dimension);
  527.         for (int i = 0; i < len; i++)
  528.         {
  529.             if (dest.Rank == n)
  530.             {
  531.                 indices[n - 1] = i;
  532.                 if (source[i] == null || elementType == typeof(object) || elementType == source[i].GetType())
  533.                 {
  534.                     dest.SetValue(source[i], indices);
  535.                 }
  536.                 else
  537.                 {
  538.                     dest.SetValue(ChangeType(source[i], elementType), indices);
  539.                 }
  540.             }
  541.             else
  542.             {
  543.                 temp[n - 1] = i;
  544.                 ArrayListToArray(source[i] as ArrayList, dest, temp, elementType);
  545.             }
  546.         }
  547.     }
  548.     private static object CreateInstance(Type type)
  549.     {
  550.         try
  551.         {
  552.             return Activator.CreateInstance(type);
  553.         }
  554.         catch
  555.         {
  556.         }
  557.         try
  558.         {
  559.             return Activator.CreateInstance(type, new object [] { 0 });
  560.         }
  561.         catch
  562.         {
  563.         }
  564.         try
  565.         {
  566.             return Activator.CreateInstance(type, new object [] { false });
  567.         }
  568.         catch
  569.         {
  570.         }
  571.         try
  572.         {
  573.             return Activator.CreateInstance(type, new object [] { "" });
  574.         }
  575.         catch
  576.         {
  577.         }
  578.         try
  579.         {
  580.             FieldInfo[] f = type.GetFields(BindingFlags.Public | BindingFlags.Static);
  581.             for (int i = 0, n = f.Length; i < n; i++)
  582.             {
  583.                 if (f[i].FieldType == type)
  584.                 {
  585.                     return f[i].GetValue(null);
  586.                 }
  587.             }
  588.         }
  589.         catch
  590.         {
  591.         }
  592.         MethodInfo[] m = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
  593.         for (int i = 0, n = m.Length; i < n; i++)
  594.         {
  595.             if (m[i].ReturnType == type)
  596.             {
  597.                 try
  598.                 {
  599.  
  600.                     return m[i].Invoke(null, null);
  601.                 }
  602.                 catch
  603.                 {
  604.                 }
  605.                 try
  606.                 {
  607.                     return m[i].Invoke(null, new object[] { 0 });
  608.                 }
  609.                 catch
  610.                 {
  611.                 }
  612.                 try
  613.                 {
  614.                     return m[i].Invoke(null, new object[] { false });
  615.                 }
  616.                 catch
  617.                 {
  618.                 }
  619.                 try
  620.                 {
  621.                     return m[i].Invoke(null, new object[] { "" });
  622.                 }
  623.                 catch
  624.                 {
  625.                 }
  626.             }
  627.         }
  628.         ThrowError("Can't create the instance of " + type.FullName);
  629.         return null;
  630.     }
  631.     public static object UnSerialize(byte[] ss)
  632.     {
  633.         return UnSerialize(ss, null, Encoding.UTF8);
  634.     }
  635.     public static object UnSerialize(byte[] ss, Encoding encoding)
  636.     {
  637.         return UnSerialize(ss, null, encoding);
  638.  
  639.     }
  640.     public static object UnSerialize(byte[] ss, Type type)
  641.     {
  642.         return UnSerialize(ss, type, Encoding.UTF8);
  643.     }
  644.     public static object UnSerialize(byte[] ss, Type type, Encoding encoding)
  645.     {
  646.         int hv = 1;
  647.         MemoryStream stream = new MemoryStream(ss);
  648.         stream.Seek(0, SeekOrigin.Begin);
  649.         object result = UnSerialize(stream, new Hashtable(), ref hv, new Hashtable(), encoding);
  650.         stream.Close();
  651.         if (type != null && result != null)
  652.         {
  653.             result = ChangeType(result, type);
  654.         }
  655.         return result;
  656.     }
  657.     private static object UnSerialize(MemoryStream stream, Hashtable ht, ref int hv, Hashtable rt, Encoding encoding)
  658.     {
  659.         switch (stream.ReadByte())
  660.         {
  661.             case __N: return ht[hv++] = ReadNull(stream);
  662.             case __b: return ht[hv++] = ReadBoolean(stream);
  663.             case __i: return ht[hv++] = ReadInteger(stream);
  664.             case __d: return ht[hv++] = ReadDouble(stream);
  665.             case __s: return ht[hv++] = ReadString(stream, encoding);
  666.             case __U: return ht[hv++] = ReadUnicodeString(stream);
  667.             case __r: return ht[hv++] = ReadRef(stream, ht, rt);
  668.             case __a: return ReadArray(stream, ht, ref hv, rt, encoding);
  669.             case __O: return ReadObject(stream, ht, ref hv, rt, encoding);
  670.             case __C: return ReadCustomObject(stream, ht, ref hv, encoding);
  671.             case __R: return ReadRef(stream, ht, rt);
  672.             default: ThrowError("Wrong Serialize Stream!"); return null;
  673.         }
  674.     }
  675.     private static string ReadNumber(MemoryStream stream)
  676.     {
  677.         StringBuilder sb = new StringBuilder();
  678.         int i = stream.ReadByte();
  679.         while (i != __Semicolon && i != __Colon)
  680.         {
  681.             sb.Append((char)i);
  682.             i = stream.ReadByte();
  683.         }
  684.         return sb.ToString();
  685.     }
  686.     private static object ReadNull(MemoryStream stream)
  687.     {
  688.         stream.Seek(1, SeekOrigin.Current);
  689.         return null;
  690.     }
  691.     private static bool ReadBoolean(MemoryStream stream)
  692.     {
  693.         stream.Seek(1, SeekOrigin.Current);
  694.         bool b = (stream.ReadByte() == __1);
  695.         stream.Seek(1, SeekOrigin.Current);
  696.         return b;
  697.     }
  698.     private static object ReadInteger(MemoryStream stream)
  699.     {
  700.         stream.Seek(1, SeekOrigin.Current);
  701.         string i = ReadNumber(stream);
  702.         bool neg = i.StartsWith("-");
  703.         try
  704.         {
  705.             return (neg ? (object)SByte.Parse(i) : (object)Byte.Parse(i));
  706.         }
  707.         catch
  708.         {
  709.             try
  710.             {
  711.                 return (neg ? (object)Int16.Parse(i) : (object)UInt16.Parse(i));
  712.             }
  713.             catch
  714.             {
  715.                 return Int32.Parse(i);
  716.             }
  717.         }
  718.     }
  719.     private static object ReadDouble(MemoryStream stream)
  720.     {
  721.         stream.Seek(1, SeekOrigin.Current);
  722.         string d = ReadNumber(stream);
  723.         if (d == "NAN") return Double.NaN;
  724.         if (d == "INF") return Double.PositiveInfinity;
  725.         if (d == "-INF") return Double.NegativeInfinity;
  726.         bool neg = d.StartsWith("-");
  727.         try
  728.         {
  729.             return UInt32.Parse(d);
  730.         }
  731.         catch
  732.         {
  733.             try
  734.             {
  735.                 return (neg ? (object)Int64.Parse(d) : (object)UInt64.Parse(d));
  736.             }
  737.             catch
  738.             {
  739.                 try
  740.                 {
  741.                     return Decimal.Parse(d);
  742.                 }
  743.                 catch
  744.                 {
  745.                     try
  746.                     {
  747.                         return Single.Parse(d);
  748.                     }
  749.                     catch
  750.                     {
  751.                         return Double.Parse(d);
  752.                     }
  753.                 }
  754.             }
  755.         }
  756.     }
  757.     private static string ReadString(MemoryStream stream, Encoding encoding)
  758.     {
  759.         stream.Seek(1, SeekOrigin.Current);
  760.         int len = Int32.Parse(ReadNumber(stream));
  761.         stream.Seek(1, SeekOrigin.Current);
  762.         byte[] buf = new byte[len];
  763.         stream.Read(buf, 0, len);
  764.         string s = encoding.GetString(buf);
  765.         stream.Seek(2, SeekOrigin.Current);
  766.         return s;
  767.     }
  768.     private static string ReadUnicodeString(MemoryStream stream)
  769.     {
  770.         stream.Seek(1, SeekOrigin.Current);
  771.         int l = Int32.Parse(ReadNumber(stream));
  772.         stream.Seek(1, SeekOrigin.Current);
  773.         StringBuilder sb = new StringBuilder(l);
  774.         int c;
  775.         for (int i = 0; i < l; i++)
  776.         {
  777.             if ((c = stream.ReadByte()) == __Slash)
  778.             {
  779.                 char c1 = (char)stream.ReadByte();
  780.                 char c2 = (char)stream.ReadByte();
  781.                 char c3 = (char)stream.ReadByte();
  782.                 char c4 = (char)stream.ReadByte();
  783.                 sb.Append((char)Int32.Parse(String.Concat(c1, c2, c3, c4), System.Globalization.NumberStyles.HexNumber));
  784.             }
  785.             else
  786.             {
  787.                 sb.Append((char)c);
  788.             }
  789.         }
  790.         stream.Seek(2, SeekOrigin.Current);
  791.         return sb.ToString();
  792.     }
  793.     private static object ReadRef(MemoryStream stream, Hashtable ht, Hashtable rt)
  794.     {
  795.         stream.Seek(1, SeekOrigin.Current);
  796.         int r = Int32.Parse(ReadNumber(stream));
  797.         if (rt.ContainsKey(r))
  798.         {
  799.             rt[r] = true;
  800.         }
  801.         return ht[r];
  802.     }
  803.     private static object ReadArray(MemoryStream stream, Hashtable ht, ref int hv, Hashtable rt, Encoding encoding)
  804.     {
  805.         stream.Seek(1, SeekOrigin.Current);
  806.         int n = Int32.Parse(ReadNumber(stream));
  807.         stream.Seek(1, SeekOrigin.Current);
  808.         Hashtable h = new Hashtable(n);
  809.         ArrayList al = new ArrayList(n);
  810.         int r = hv;
  811.         rt.Add(r, false);
  812.         long p = stream.Position;
  813.         ht[hv++] = h;
  814.         for (int i = 0; i < n; i++)
  815.         {
  816.             object key, value;
  817.             switch (stream.ReadByte())
  818.             {
  819.                 case __i: key = Convert.ToInt32(ReadInteger(stream)); break;
  820.                 case __s: key = ReadString(stream, encoding); break;
  821.                 case __U: key = ReadUnicodeString(stream); break;
  822.                 default: ThrowError("Wrong Serialize Stream!"); return null;
  823.             }
  824.             value = UnSerialize(stream, ht, ref hv, rt, encoding);
  825.             if (al != null)
  826.             {
  827.                 if ((key is Int32) && (int)key == i)
  828.                 {
  829.                     al.Add(value);
  830.                 }
  831.                 else
  832.                 {
  833.                     al = null;
  834.                 }
  835.             }
  836.             h[key] = value;
  837.         }
  838.         if (al != null)
  839.         {
  840.             ht[r] = al;
  841.             if ((bool)rt[r])
  842.             {
  843.                 hv = r + 1;
  844.                 stream.Position = p;
  845.                 for (int i = 0; i < n; i++)
  846.                 {
  847.                     int key;
  848.                     switch (stream.ReadByte())
  849.                     {
  850.                         case __i: key = Convert.ToInt32(ReadInteger(stream)); break;
  851.                         default: ThrowError("Wrong Serialize Stream!"); return null;
  852.                     }
  853.                     al[key] = UnSerialize(stream, ht, ref hv, rt, encoding);
  854.                 }
  855.             }
  856.         }
  857.         rt.Remove(r);
  858.         stream.Seek(1, SeekOrigin.Current);
  859.         return ht[r];
  860.     }
  861.     private static object ReadObject(MemoryStream stream, Hashtable ht, ref int hv, Hashtable rt, Encoding encoding)
  862.     {
  863.         stream.Seek(1, SeekOrigin.Current);
  864.         int len = Int32.Parse(ReadNumber(stream));
  865.         stream.Seek(1, SeekOrigin.Current);
  866.         byte[] buf = new byte[len];
  867.         stream.Read(buf, 0, len);
  868.         string cn = encoding.GetString(buf);
  869.         stream.Seek(2, SeekOrigin.Current);
  870.         int n = Int32.Parse(ReadNumber(stream));
  871.         stream.Seek(1, SeekOrigin.Current);
  872.         Type type = GetType(cn);
  873.         object o;
  874.         if (type != null)
  875.         {
  876.             try
  877.             {
  878.                 o = CreateInstance(type);
  879.             }
  880.             catch
  881.             {
  882.                 o = new Hashtable(n);
  883.             }
  884.         }
  885.         else
  886.         {
  887.             o = new Hashtable(n);
  888.         }
  889.         ht[hv++] = o;
  890.         for (int i = 0; i < n; i++)
  891.         {
  892.             string key;
  893.             switch (stream.ReadByte())
  894.             {
  895.                 case __s: key = ReadString(stream, encoding); break;
  896.                 case __U: key = ReadUnicodeString(stream); break;
  897.                 default: ThrowError("Wrong Serialize Stream!"); return null;
  898.             }
  899.             if (key.Substring(0, 1) == "\0")
  900.             {
  901.                 key = key.Substring(key.IndexOf("\0", 1) + 1);
  902.             }
  903.             if (o is Hashtable)
  904.             {
  905.                 ((Hashtable)o)[key] = UnSerialize(stream, ht, ref hv, rt, encoding);
  906.             }
  907.             else
  908.             {
  909.                 type.InvokeMember(key, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetField, null, o, new object[] { UnSerialize(stream, ht, ref hv, rt, encoding) });
  910.             }
  911.         }
  912.         stream.Seek(1, SeekOrigin.Current);
  913.         MethodInfo __wakeup = null;
  914.         try
  915.         {
  916.             __wakeup = o.GetType().GetMethod("__wakeup", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase, null, new Type[0], new ParameterModifier[0]);
  917.         }
  918.         catch { }
  919.         if (__wakeup != null)
  920.         {
  921.             __wakeup.Invoke(o, null);
  922.         }
  923.         return o;
  924.     }
  925.     private static object ReadCustomObject(MemoryStream stream, Hashtable ht, ref int hv, Encoding encoding)
  926.     {
  927.         stream.Seek(1, SeekOrigin.Current);
  928.         int len = Int32.Parse(ReadNumber(stream));
  929.         stream.Seek(1, SeekOrigin.Current);
  930.         byte[] buf = new byte[len];
  931.         stream.Read(buf, 0, len);
  932.         string cn = encoding.GetString(buf);
  933.         stream.Seek(2, SeekOrigin.Current);
  934.         int n = Int32.Parse(ReadNumber(stream));
  935.         stream.Seek(1, SeekOrigin.Current);
  936.         Type type = GetType(cn);
  937.         object o;
  938.         if (type != null)
  939.         {
  940.             o = CreateInstance(type);
  941.         }
  942.         else
  943.         {
  944.             ThrowError(String.Concat("Type ", cn, " is undefined!"));
  945.             return null;
  946.         }
  947.         ht[hv++] = o;
  948.         if (o is Serializable)
  949.         {
  950.             byte[] b = new byte[n];
  951.             stream.Read(b, 0, n);
  952.             ((Serializable)o).UnSerialize(b);
  953.         }
  954.         else
  955.         {
  956.             stream.Seek(n, SeekOrigin.Current);
  957.         }
  958.         stream.Seek(1, SeekOrigin.Current);
  959.         return o;
  960.     }
  961.     private static void ThrowError(string message)
  962.     {
  963.         throw new UnSerializeException(message);
  964.     }
  965.     private static Type GetType(string typeName)
  966.     {
  967.         Type type = Type.GetType(typeName, false, true);
  968.         if (type != null) return type;
  969.         foreach (DictionaryEntry e in __ns)
  970.         {
  971.             type = Type.GetType(String.Concat((string)e.Key, ".", typeName, ", ", (string)e.Value), false, true);
  972.             if (type != null) return type;
  973.         }
  974.         return null;
  975.     }
  976. }

原创作品,转载请注明出处。

标签: PHP, .NET

« 上一篇 | 下一篇 »

只显示10条记录相关文章

发表评论

评论 (必须):