具有 System.Object 对象的 XmlSerializer

本文关键字:XmlSerializer 对象 Object System 具有 | 更新日期: 2023-09-27 18:33:33

我似乎找不到对此的明确回应,这让我发疯。 XmlSerializer 类似乎适用于定义的任何内容,甚至适用于嵌套类。 但是当其中一个类包含 System.Object 时,它会呕吐。 有谁知道解决这个问题的简单方法?

namespace test
{
    public class SomeList
    {
        public object obj;
    }
    public class Person
    {
        public string first;
        public string last;
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Creating object...");
                Person me = new Person();
                me.first = "MyFirst";
                me.last = "MyLast";
                Console.WriteLine("- Serialized: " + serialize_xml<Person>(me));
                Console.WriteLine("");
                Console.WriteLine("Creating object with embedded generic...");
                SomeList test = new SomeList();
                test.obj = me;
                Console.WriteLine("- Serialized: " + serialize_xml<SomeList>(test));
                Console.WriteLine("");
                Console.Write("Press ENTER to exit.");
                Console.ReadLine();
                return;
            }
            catch (Exception e)
            {
                print_exception(e);
                Console.WriteLine("");
                Console.Write("Press ENTER to exit.");
                Console.ReadLine();
                return;
            }
        }
        static string serialize_xml<T>(T obj)
        {
            XmlSerializer xmls = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add("", "");
                settings.Encoding = Encoding.UTF8;
                settings.Indent = false;
                settings.NewLineChars = "";
                settings.NewLineHandling = NewLineHandling.None;
                settings.NewLineOnAttributes = false;
                settings.ConformanceLevel = ConformanceLevel.Document;
                settings.OmitXmlDeclaration = true;
                using (XmlWriter writer = XmlTextWriter.Create(ms, settings))
                {
                    xmls.Serialize(writer, obj, ns);
                }
                string xml = Encoding.UTF8.GetString(ms.ToArray());
                // remove the BOM character at the beginning which screws up decoding
                if (xml.Length > 0 && xml[0] != '<')
                {
                    xml = xml.Substring(1, xml.Length - 1);
                }
                return xml;
            }
        }
        static void print_exception(Exception e)
        {
            Console.WriteLine(" = Exception Type: " + e.GetType().ToString());
            Console.WriteLine(" = Exception Dat " + e.Data);
            Console.WriteLine(" = Inner Exception: " + e.InnerException);
            Console.WriteLine(" = Exception Message: " + e.Message);
            Console.WriteLine(" = Exception Source: " + e.Source);
            Console.WriteLine(" = Exception StackTrace: " + e.StackTrace);
        }
    }
}

在控制台上创建以下输出:

 = Exception Type: System.InvalidOperationException
 = Exception Dat System.Collections.ListDictionaryInternal
 = Inner Exception: System.InvalidOperationException: The type test.Person was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
   at System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(String name, String ns, Object o, Boolean xsiType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeList.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeList.Write2_SomeList(String n, String ns,SomeList o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeList.Write3_SomeList(Object o)
 = Exception Message: There was an error generating the XML document.
 = Exception Source: System.Xml
 = Exception StackTrace:    at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces)
   at test.Program.serialize_xml[T](T obj) in C:'Users'jchristn'Documents'Visual Studio 2010'Projects'test'test'Program.cs:line 83
   at test.Program.Main(String[] args) in C:'Users'jchristn'Documents'Visual Studio 2010'Projects'test'test'Program.cs:line 47

具有 System.Object 对象的 XmlSerializer

假设有

一组固定的对象SomeList.obj可以包含,并且该集合在编译时是已知的,您可以使用XmlIncludeAttribute在容器类上指定它们:

[XmlInclude(typeof(Person))]
[XmlInclude(typeof(Other))]
public class SomeList
{
    public object obj;
}
public class Person
{
    public string first;
    public string last;
}
public class Other
{
    public int MyProperty { get; set; }
}
如果类型在

编译时未知,则可以在 XmlSerializer 构造函数的重载中指定类型数组:

XmlSerializer xmls = new XmlSerializer(typeof(T), new Type[] { <...types...> });