简体   繁体   中英

XmlSerializer System.InvalidOperationException

I have the following code in my application:

[Serializable]
public class Class
{
    private string name = "";
    private List<Property> property = new List<Property>();
    [XmlAttribute]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    [XmlArray(ElementName = "Properties")]
    public List<Property> Property
    {
        get { return property; }
        set { property = value; }
    }
    public Class() { }
}
[Serializable]
public class Property
{
    private string name = "";
    private object value;

    [XmlAttribute]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    [XmlElement]
    public object Value
    {
        get { return this.value; }
        set { this.value = value; }
    }
    public Property() { }
}
class Program
{
    static void Main(string[] args)
    {
        List<Class> classList = GetClassList();
        SerializeConfig("test.xml", classList);
    }
    private static List<Class> GetClassList()
    {
        return new List<Class>(){
            new Class()
            {
                Name = "MyFirstClass",
                Property = new List<Property>() {
                    new Property(){ Name = "StringProperty",    Value = "Simple1"},
                    new Property(){ Name = "IntProperty",       Value = 3},
                    new Property(){ Name = "DoubleProperty",    Value = 5.5},
                    new Property(){ Name = "ListProperty",      Value = new List<int>(){
                        1,2,3,4,5
                        }
                    },
                }
            }
        };
    }
    public static List<Class> DeserializeConfig(string configPath)
    {
        if (!File.Exists(configPath)) return null;
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<Class>), new XmlRootAttribute("Classes"));
            using (FileStream fs = File.Open(configPath, FileMode.Open))
            {
                return (List<Class>)serializer.Deserialize(fs);
            }
        }
        catch (Exception)
        {
            return null;
        }
    }
    public static bool SerializeConfig(string path, List<Class> config)
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<Class>), new XmlRootAttribute("Classes"));
            using (FileStream fs = File.Open(path, FileMode.Create))
            {
                serializer.Serialize(fs, config);
            }
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }
}

If you run this code, you will get a System.InvalidOperationException with the following message:

{System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] may not be used in this context.
   at System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(String name, String ns, Object o, Boolean xsiType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterList1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterList1.Write2_Property(String n, String ns, Property o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterList1.Write3_Class(String n, String ns, Class o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterList1.Write4_Classes(Object o)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o, XmlSerializerNamespaces namespaces)
   at System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o)
   at SerializeTest.Program.SerializeConfig(String path, List`1 config) in [...]\Program.cs:line 102}

Why I can't serialize the List in this way? How I can build a workaround?

Okay, I found the solution. I have to add custom type.

XmlSerializer serializer = new XmlSerializer(typeof(List<Class>), null, new Type[] { typeof(List<int>) }, new XmlRootAttribute("Classes"),"");

So I have to collect all types from my list:

private static Type[] CollectTypesFromCollection(List<Class> collection)
{
    List<Type> types = new List<Type>();
    foreach (Class item in collection)
        foreach (Property property in item.Property)
            if (!types.Contains(property.Value.GetType()))
                types.Add(property.Value.GetType());
    return types.ToArray();
}

and can use the serializer like this:

XmlSerializer serializer = new XmlSerializer(typeof(List<Class>),null,CollectTypesFromCollection(config), new XmlRootAttribute("Classes"),"");

I would recommend to have a look at this before you go into XML Serialization where the error occurs because of the way of List creation.

Introducing XML Serialization

Reference: XmlSerializer List Item Element Name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM