Kelvin.cs
上传用户:huiyue
上传日期:2022-04-08
资源大小:1429k
文件大小:18k
源码类别:

搜索引擎

开发平台:

ASP/ASPX

  1. using System;
  2. using System.Xml.Serialization;
  3. using System.Runtime.Serialization;
  4. /// <summary>
  5. /// Store objects at absolute zero, and thaw for use as required
  6. /// </summary>
  7. /// <remarks>
  8. /// Kelvin can serialize and deserialize any type of object 
  9. /// (well, it has to be serializable to start with - I just mean it uses Generics)
  10. /// Use Xml (String) or Binary (Byte[]) datastructures or read/write files of both types.
  11. /// </remarks>
  12. /// <typeparam name="T">Type/Class that you wish to serialize/deserialize/</typeparam>
  13. /// <example>
  14. /// Kelvin is a *static* class to provide simple, single-line, typed access to Serialization:
  15. /// <code><![CDATA[
  16. /// Catalog currentCatalog = new Catalog ();
  17. /// // ... currentCatalog population ...
  18. /// // Save to disk
  19. /// Kelvin<Catalog>.FreezeToBinaryFile(currentCatalog, @"C:TempCatalog.dat");
  20. /// // Load from disk
  21. /// Catalog loadedCatalog = Kelvin<Catalog>.ThawFromBinaryFile(@"C:TempCatalog.dat");
  22. /// 
  23. /// string[] words = new string[] {"Sample", "Array", "of", "Words"};
  24. /// Kelvin<string[]>.FreezeToXmlFile(words, @"C:TempWords.xml.");
  25. /// string[] loadedWords = Kelvin<string[]>.ThawFromXmlFile(@"C:TempWords.xml");
  26. /// ]]></code>
  27. /// </example>
  28. namespace cd.net
  29. {
  30.     public static class Kelvin<T> // where T : ISerializable // prevents string[] from being Serialized
  31.     {
  32.         #region Static Constructor (empty)
  33.         /// <summary>
  34.         /// Kelvin cannot be instantiated. All methods are static. 
  35.         /// Nested classes are not static, but are only used internally.
  36.         /// </summary>
  37.         static Kelvin() { }
  38.         #endregion
  39.         #region To/From a File
  40.         /// <summary>
  41.         /// Serialize object to an XML file on disk
  42.         /// </summary>
  43.         /// <param name="cryo">T instance to serialize</param>
  44.         /// <param name="fileName">Full file path, including name and extension, eg @"C:TempNewFile.xml"</param>
  45.         /// <returns>true if save was successful, false if an error occured</returns>
  46.         public static bool ToXmlFile(T cryo, string fileName)
  47.         {
  48.             try
  49.             {
  50.                 XmlSerializer serializerXml = new XmlSerializer(typeof(T));
  51.                 System.IO.TextWriter writer = new System.IO.StreamWriter(fileName);
  52.                 serializerXml.Serialize(writer, cryo);
  53.                 writer.Close();
  54.                 return true;
  55.             }
  56.             catch (System.IO.DirectoryNotFoundException)
  57.             {
  58.                 return false;
  59.             }
  60.         }
  61.         /// <summary>
  62.         /// Deserialize an Xml File to T object
  63.         /// </summary>
  64.         /// <param name="frozenObjectFileName">Full file path, including name and extension, eg @"C:TempNewFile.xml"</param>
  65.         /// <returns>T instance or default(T)</returns>
  66.         public static T FromXmlFile(string frozenObjectFileName)
  67.         {
  68.             XmlSerializer serializerXml = new XmlSerializer(typeof(T));
  69.             if (System.IO.File.Exists(frozenObjectFileName))
  70.             {
  71.                 System.IO.Stream stream = new System.IO.FileStream(frozenObjectFileName, System.IO.FileMode.Open);
  72.                 object o = serializerXml.Deserialize(stream);
  73.                 stream.Close();
  74.                 return (T)o;
  75.             }
  76.             else
  77.             {
  78.                 throw new System.IO.FileNotFoundException(frozenObjectFileName + " was not found.");
  79.             }
  80.         }
  81.         /// <summary>
  82.         /// Load Xml from a Url and deserialize
  83.         /// </summary>
  84.         public static T FromXmlResponse(string frozenObjectXmlUrl)
  85.         {
  86.             XmlSerializer serializer = new XmlSerializer(typeof(T));
  87.             System.Net.WebClient client = new System.Net.WebClient();
  88.             using (System.IO.Stream stream = client.OpenRead(frozenObjectXmlUrl))
  89.             {
  90.                 object o = serializer.Deserialize(stream);
  91.                 stream.Close();
  92.                 return (T)o;
  93.             }
  94.         }
  95.         /// <summary>
  96.         /// Load Xml stream from the given assembly/resource-name and deserialize
  97.         /// </summary>
  98.         /// <param name="a">Assembly object</param>
  99.         /// <param name="frozenObjectResourceName">Resource filename</param>
  100.         public static T FromResource(System.Reflection.Assembly a, string frozenObjectResourceName)
  101.         {
  102.             XmlSerializer serializer = new XmlSerializer(typeof(T));
  103.             System.Net.WebClient client = new System.Net.WebClient();
  104.             using (System.IO.Stream stream = a.GetManifestResourceStream(frozenObjectResourceName))
  105.             {
  106.                 object o = serializer.Deserialize(stream);
  107.                 stream.Close();
  108.                 return (T)o;
  109.             }
  110.         }
  111.         #endregion
  112.         #region To/From a String
  113.         /// <summary>
  114.         /// Serialize object to an Xml String for use in your code
  115.         /// </summary>
  116.         /// <param name="cryo">T instance to serialize</param>
  117.         /// <returns><see cref="System.String"/> representation of T object</returns>
  118.         public static string ToXmlString(T cryo)
  119.         {
  120.             XmlSerializer serializer = new XmlSerializer(typeof(T));
  121.             System.IO.TextWriter writer = new System.IO.StringWriter();
  122.             try
  123.             {
  124.                 serializer.Serialize(writer, cryo);
  125.             }
  126.             finally
  127.             {
  128.                 writer.Flush();
  129.                 writer.Close();
  130.             }
  131.             return writer.ToString();
  132.         }
  133.         /// <summary>
  134.         /// Deserialize a String containing Xml to T object
  135.         /// </summary>
  136.         /// <param name="frozen"></param>
  137.         /// <returns>T instance or default(T)</returns>
  138.         public static T FromXml(string frozen)
  139.         {
  140.             if (frozen.Length <= 0) throw new ArgumentOutOfRangeException("frozenObject", "Cannot thaw a zero-length string");
  141.             XmlSerializer serializer = new XmlSerializer(typeof(T));
  142.             System.IO.TextReader reader = new System.IO.StringReader(frozen);
  143.             object @object = default(T);    // default return value
  144.             try
  145.             {
  146.                 @object = serializer.Deserialize(reader);
  147.             }
  148.             finally
  149.             {
  150.                 reader.Close();
  151.             }
  152.             return (T)@object;
  153.         }
  154.         #endregion
  155.         #region To/From Xml
  156.         /// <summary>
  157.         /// Serialize object to an XmlDocument for use in your code
  158.         /// </summary>
  159.         /// <param name="cryo">T instance to serialize</param>
  160.         /// <returns><see cref="System.Xml.XmlDocument"/> representation of T object</returns>
  161.         public static System.Xml.XmlDocument ToXmlDocument(T cryo)
  162.         {
  163.             XmlSerializer serializer = new XmlSerializer(typeof(T));
  164.             System.Xml.XmlDocument xml = new System.Xml.XmlDocument();
  165.             using (System.IO.Stream stream = new System.IO.MemoryStream())
  166.             {
  167.                 serializer.Serialize(stream, cryo);
  168.                 stream.Position = 0;
  169.                 xml.Load(stream);
  170.             }
  171.             return xml;
  172.         }
  173.         /// <summary>
  174.         /// Deserialize an XmlDocument to T object
  175.         /// </summary>
  176.         /// <param name="frozen">XmlDocument to deserialize</param>
  177.         /// <returns>T instance</returns>
  178.         public static T FromXml(System.Xml.XmlDocument frozen)
  179.         {
  180.             XmlSerializer serializer = new XmlSerializer(typeof(T));
  181.             System.IO.Stream stream = new System.IO.MemoryStream();
  182.             frozen.Save(stream);
  183.             try
  184.             {
  185.                 stream.Position = 0;
  186.                 return (T)serializer.Deserialize(stream);
  187.             }
  188.             finally
  189.             {
  190.                 stream.Close();
  191.             }
  192.         }
  193.         #endregion
  194.         #region To/From a binary File
  195.         /// <summary>
  196.         /// Serialize object to a Binary file on disk
  197.         /// </summary>
  198.         /// <param name="cryo">T instance to serialize</param>
  199.         /// <param name="fileName">Full file path, including name and extension, eg @"C:TempNewFile.dat"</param>
  200.         /// <returns>true if save was successful, false if an error occured</returns>
  201.         public static bool ToBinaryFile(T cryo, string fileName)
  202.         {
  203.             try
  204.             {
  205.                 System.IO.Stream stream = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
  206.                 System.Runtime.Serialization.IFormatter formatter
  207.                     = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  208.                 formatter.Serialize(stream, cryo);
  209.                 stream.Close();
  210.                 return true;
  211.             }
  212.             catch (System.IO.DirectoryNotFoundException)
  213.             {
  214.                 return false;
  215.             }
  216.         }
  217.         /// <summary>
  218.         /// Deserialize a Binary File to T object
  219.         /// </summary>
  220.         /// <param name="frozenObjectFileName">Full file path, including name and extension, eg @"C:TempNewFile.xml"</param>
  221.         /// <returns>T instance or default(T)</returns>
  222.         public static T FromBinaryFile(string frozenObjectFileName)
  223.         {
  224.             if (System.IO.File.Exists(frozenObjectFileName))
  225.             {
  226.                 System.IO.Stream stream = new System.IO.FileStream(frozenObjectFileName, System.IO.FileMode.Open);
  227.                 System.Runtime.Serialization.IFormatter formatter
  228.                     = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  229.                 try
  230.                 {
  231.                     return (T)formatter.Deserialize(stream); // This doesn't work, SerializationException "Cannot find the assembly <random name>"
  232.                 }
  233.                 catch (System.Runtime.Serialization.SerializationException)
  234.                 {   // "Unable to find assembly 'App_Code.vj-e_8q4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'."
  235.                     // or                       "App_Code.y4xkvcpq, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null."
  236.                     // and try the same operation with a custom Binder class that tries to resolve types locally.
  237.                     try
  238.                     {
  239.                         stream.Position = 0;
  240.                         formatter.Binder = new GenericBinder();
  241.                         return (T)formatter.Deserialize(stream); // // Try the custom BasicBinder to see if that helps us 'find' the assembly
  242.                     }
  243.                     catch
  244.                     {
  245.                         throw;
  246.                     }
  247.                 }
  248.                 finally
  249.                 {
  250.                     stream.Close();
  251.                 }
  252.             }
  253.             else
  254.             {
  255.                 throw new System.IO.FileNotFoundException(frozenObjectFileName+" was not found.");
  256.             }
  257.         }
  258.         #endregion
  259.         #region To/From a Byte[]
  260.         /// <summary>
  261.         /// Serialize object to a Byte[] array for use in your code
  262.         /// </summary>
  263.         /// <param name="cryo">T instance to serialize</param>
  264.         /// <returns>Array of <see cref="System.Byte"/> representing T object</returns>
  265.         public static Byte[] ToBinary(T cryo)
  266.         {
  267.             System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
  268.                 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  269.             System.IO.Stream stream = new System.IO.MemoryStream();
  270.             try
  271.             {
  272.                 formatter.Serialize(stream, cryo);
  273.                 byte[] bytes = new byte[stream.Length];
  274.                 stream.Seek(0, System.IO.SeekOrigin.Begin);
  275.                 stream.Read(bytes, 0, bytes.Length);
  276.                 return bytes;
  277.             }
  278.             finally
  279.             {
  280.                 stream.Close();
  281.             }
  282.         }
  283.         /// <summary>
  284.         /// Deserialize a Byte Array to T object
  285.         /// </summary>
  286.         /// <param name="frozen">Array of <see cref="System.Byte"/> containing a previously serialized object</param>
  287.         /// <returns>T instance or null</returns>
  288.         public static T FromBinary(Byte[] frozen)
  289.         {
  290.             if (frozen.Length <= 0) throw new ArgumentOutOfRangeException("frozenObject", "Cannot thaw a zero-length Byte[] array");
  291.             System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
  292.                 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  293.             System.IO.Stream stream = new System.IO.MemoryStream(frozen);
  294.             try
  295.             {
  296.                 return (T)formatter.Deserialize(stream);
  297.             }
  298.             finally
  299.             {
  300.                 stream.Close();
  301.             }
  302.         }
  303.         /// <summary>
  304.         /// Deserialize a Byte Array to T object, using a custom Binder 
  305.         /// to help resolve the types referred to in the serialized stream
  306.         /// </summary>
  307.         /// <param name="frozen">Array of <see cref="System.Byte"/> containing a previously serialized object</param>
  308.         /// <param name="customBinder">Subclass of <see cref="System.Runtime.Serialization.SerializationBinder"/></param>
  309.         /// <returns>T instance or null</returns>
  310.         public static T FromBinary(Byte[] frozen, System.Runtime.Serialization.SerializationBinder customBinder)
  311.         {
  312.             if (frozen.Length <= 0) throw new ArgumentOutOfRangeException("frozenObject", "Cannot thaw a zero-length Byte[] array");
  313.             if (customBinder == null) throw new ArgumentNullException("customBinder", "SerializationBinder implementation cannot be null");
  314.             System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
  315.                 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  316.             formatter.Binder = customBinder;
  317.             System.IO.Stream stream = new System.IO.MemoryStream(frozen);
  318.             try
  319.             {
  320.                 return (T)formatter.Deserialize(stream);
  321.             }
  322.             finally
  323.             {
  324.                 stream.Close();
  325.             }
  326.         }
  327.         #endregion
  328.         #region TODO: To/From SqlXml
  329.         /// <summary>
  330.         /// Serialize object to a SqlXml instance for saving to a SqlServer2005 XML column
  331.         /// </summary>
  332.         /// <param name="cryo"></param>
  333.         /// <returns></returns>
  334.         public static System.Data.SqlTypes.SqlXml ToSqlXml(T cryo)
  335.         {
  336.             throw new NotImplementedException("SqlXml type not implemented");
  337.         }
  338.         /// <summary>
  339.         /// Serialize object to a Byte[] array for use in your code
  340.         /// </summary>
  341.         /// <param name="frozen"></param>
  342.         /// <returns></returns>
  343.         public static T FromSqlXml(System.Data.SqlTypes.SqlXml frozen)
  344.         {
  345.             throw new NotImplementedException("SqlXml type not implemented");
  346.         }
  347.         #endregion
  348.         #region Private SerializationBinder helper classes
  349.         /// <summary>
  350.         /// Attempt to resolve type names by looking in the assembly where T is declared
  351.         /// </summary>
  352.         /// <remarks>
  353.         /// http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.binder.aspx
  354.         /// http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx
  355.         /// </remarks>
  356.         public class GenericBinder : System.Runtime.Serialization.SerializationBinder
  357.         {
  358.             /// <summary>
  359.             /// Resolve type
  360.             /// </summary>
  361.             /// <param name="assemblyName">eg. App_Code.y4xkvcpq, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</param>
  362.             /// <param name="typeName">eg. String</param>
  363.             /// <returns>Type for the deserializer to use</returns>
  364.             public override Type BindToType(string assemblyName, string typeName)
  365.             {
  366.                 // We're going to ignore the assembly name, and assume it's in the same assembly 
  367.                 // that <T> is defined (it's either T or a field/return type within T anyway)
  368.                 string[] typeInfo = typeName.Split('.');
  369.                 bool isSystem = (typeInfo[0].ToString() == "System");
  370.                 string className = typeInfo[typeInfo.Length - 1];
  371.                 // noop is the default, returns what was passed in
  372.                 Type toReturn = Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
  373.                 if (!isSystem && (toReturn == null))
  374.                 {   // don't bother if system, or if the GetType worked already (must be OK, surely?)
  375.                     System.Reflection.Assembly a = System.Reflection.Assembly.GetAssembly(typeof(T));
  376.                     string assembly = a.FullName.Split(',')[0];   //FullName example: "App_Code.y4xkvcpq, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
  377.                     if (a == null)
  378.                     {
  379.                         throw new ArgumentException("Assembly for type '" + typeof(T).Name.ToString() + "' could not be loaded.");
  380.                     }
  381.                     else
  382.                     {
  383.                         Type newtype = a.GetType(assembly + "." + className);
  384.                         if (newtype == null)
  385.                         {
  386.                             throw new ArgumentException("Type '" + typeName + "' could not be loaded from assembly '" + assembly + "'.");
  387.                         }
  388.                         else
  389.                         {
  390.                             toReturn = newtype;
  391.                         }
  392.                     }
  393.                 }
  394.                 return toReturn;
  395.             }
  396.         }
  397.         #endregion
  398.     }
  399. }