Constructor of a XmlSerializer serializing a List throws an InvalidOperationException when used with XmlAttributeOverrides

后端 未结 1 1446
悲哀的现实
悲哀的现实 2020-12-21 08:30

Summary

When using the XmlSerializer class, serializing a List (where T can be serialized with XmlSerialize

相关标签:
1条回答
  • 2020-12-21 09:13

    Your problem is that you are trying to use overrides to attach [XmlArray] and [XmlArrayItem] to the type List<T>. However, as shown in the docs, [XmlArray] cannot be used in this manner:

    [AttributeUsageAttribute(AttributeTargets.Property | AttributeTargets.Field 
                            | AttributeTargets.Parameter | AttributeTargets.ReturnValue, 
        AllowMultiple = false)]
    public class XmlArrayAttribute : Attribute
    

    Notice there is no AttributeTargets.Class included? That means that [XmlArray] cannot be applied directly to a type and so attempting to do so via XML overrides rightly throws an exception.

    But as to why that exception message states,

    System.InvalidOperationException: XmlRoot and XmlType attributes may not be specified for the type System.Collections.Generic.List`1...

    Er, well, that message is simply wrong. It would appear to be a minor bug in XmlSerializer. You could even report it to Microsoft if you want.

    What you need to do instead is:

    • Override the [XmlRoot] attribute of List<T> to specify the desired name, in this case "texparams", AND

    • Override the [XmlType] attribute of T and set XmlTypeAttribute.TypeName to be the desired collection element name. In the absence of an [XmlArrayItem(name)] override this is what controls the element names of collections whose items are of type T.

    Thus your code should look like:

    static XmlSerializer MakeListSerializer<T>(string rootName, string elementName)
    {
        xmls.XmlAttributeOverrides attributeOverrides = new xmls.XmlAttributeOverrides();
        attributeOverrides.Add(typeof(List<T>), new xmls.XmlAttributes()
        {
            XmlRoot = new xmls.XmlRootAttribute(rootName),
        });
        attributeOverrides.Add(typeof(T), new xmls.XmlAttributes()
        {
            XmlType = new xmls.XmlTypeAttribute(elementName),
        });
    
        return new XmlSerializer(typeof(List<T>), attributeOverrides);
    }
    

    Sample fiddle.

    Note that when constructing an XmlSerializer using XmlAttributeOverrides you must cache the serializer for later reuse to avoid a severe memory leak, for reasons explained here.

    0 讨论(0)
提交回复
热议问题