How to XML deserialize an object of Unknown Type?

2020-02-15 06:36发布

问题:

I want to save my object to hard disk (like cache) with XmlSerializer. In this case, I don't have any problem.

However, when I want to deserialize this XML to an object, I get an error. Is there any way to deserialize XML to an unknown object or to an object that I created?

回答1:

There is no way in .Net to deserialize to unknown object.

To successfully serialize/deserialize an XML object the class must have default constructor. The best way is to show us the exact error message. Can you do that?



回答2:

Why not first serialize the Type of your class (System.Type class is Serializable)?

Then you can check which type was serialized and create the proper instance.



回答3:

Assuming C#

This is my solution: Just save the string to a text file or whatever you want to name it.

Here is the usage:

var xmlString = XmlHelper.Serialize(myObject);
var myNewObject = XmlHelper.Deserialize<myObjectType>(xmlString);

Here is the Class:

public static class XmlHelper
    {
        /// <summary>
        /// Gets the XML from an object, used like: var test = this.Serialize(response); for troubleshooting.
        /// </summary>
        /// <param name="pObject">The object.</param>
        /// <returns></returns>
        public static string Serialize(object pObject)
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(pObject.GetType());
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            serializer.Serialize(sw, pObject);
            return Beautify(sb.ToString());
        }

        /// <summary>
        /// Deserializes the specified input.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public static T Deserialize<T>(string input)
        where T : class
        {
            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));

            using (StringReader sr = new StringReader(input))
                return (T)ser.Deserialize(sr);
        }

        /// <summary>
        /// Beautifies the specified XML stuff.
        /// </summary>
        /// <param name="xmlStuff">The XML stuff.</param>
        /// <returns></returns>
        public static string Beautify(string xmlStuff)
        {
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(xmlStuff);

            string strRetValue = null;
            System.Text.Encoding enc = System.Text.Encoding.UTF8;
            // enc = new System.Text.UTF8Encoding(false);

            System.Xml.XmlWriterSettings xmlWriterSettings = new System.Xml.XmlWriterSettings
            {
                Encoding = enc,
                Indent = true,
                IndentChars = "    ",
                NewLineChars = "\r\n",
                NewLineHandling = System.Xml.NewLineHandling.Replace,
                //xmlWriterSettings.OmitXmlDeclaration = true;
                ConformanceLevel = System.Xml.ConformanceLevel.Document
            };


            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(ms, xmlWriterSettings))
                {
                    doc.Save(writer);
                    writer.Flush();
                    ms.Flush();

                    writer.Close();
                } // End Using writer

                ms.Position = 0;
                using (System.IO.StreamReader sr = new System.IO.StreamReader(ms, enc))
                {
                    // Extract the text from the StreamReader.
                    strRetValue = sr.ReadToEnd();

                    sr.Close();
                } // End Using sr

                ms.Close();
            } // End Using ms


            /*
            System.Text.StringBuilder sb = new System.Text.StringBuilder(); // Always yields UTF-16, no matter the set encoding
            using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb, settings))
            {
                doc.Save(writer);
                writer.Close();
            } // End Using writer
            strRetValue = sb.ToString();
            sb.Length = 0;
            sb = null;
            */

            xmlWriterSettings = null;
            return strRetValue;
        } // End Function Beautify
    }


回答4:

Another, more efficent (than either DOM or SAX) data binding approach is in this article:



回答5:

you can use SerializationHelper.DeSerializeNow as described in my post: http://borismod.blogspot.com/2008/07/nunit-serialization-test.html

internal class SerializationHelper
{
  private static readonly string DefaultFilePath = "test.dat";

  internal static void SerializeNow(object c)
  {
    SerializeNow(c, DefaultFilePath);
  }

  internal static void SerializeNow(object c, string filepath)
  {
   FileInfo f = new FileInfo(filepath);
   using (Stream s = f.Open(FileMode.Create))
   {
      BinaryFormatter b = new BinaryFormatter();
    b.Serialize(s, c);
   }
  }

  internal static object DeSerializeNow()
  {
    return DeSerializeNow(DefaultFilePath);
  }

  internal static object DeSerializeNow(string filepath)
  {
    FileInfo f = new FileInfo(filepath);
    using (Stream s = f.Open(FileMode.Open))
    {
      BinaryFormatter b = new BinaryFormatter();
      return b.Deserialize(s);
    }
  }
}