.NET XML序列化错误:选择标识符的值无效或缺失

时间:2014-09-10 15:32:15

标签: c# .net xml wpf serialization

遵循以下指示:

.NET XML Serialization error (There was an error reflecting type)

Create object based on XmlChoiceIdentifier

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlchoiceidentifierattribute(v=vs.110).aspx

我尝试使用XmlChoiceIdentifier属性序列化对象数组。但显然The Serializer需要一个数组,ObservableCollection会导致Serializer抛出错误(第一个链接)。我真的需要一个ObservableCollection来保持UI的更新。所以我试图做的是让Serialization引擎访问数组,而UI将以浪费时间的方式访问Observable集合,albiet。

这是我的“解决方案”

 [XmlType(IncludeInSchema = false)]
public enum ItemChoiceType
{
    [XmlEnumAttribute("Item")]
    Item,
    [XmlEnumAttribute("Macro")]
    Macro
}

[Serializable()]
public class GroupAndItemsCollection
{
    [XmlElementAttribute(IsNullable = false)]
    [XmlIgnore]
    public ItemChoiceType[] ItemTypeArray;

    [XmlAttribute(AttributeName = "name")]
    public string Group
    {
        get { return m_Group; }
        set
        {
            if (m_Group == value)
                return;
            m_Group = value;
            //OnPropertyChanged("Group");
        }
    }

    private ObservableCollection<ListItemName> m_items;
    private ListItemName[] m_itemsArray;

    [XmlIgnore]
    public ObservableCollection<ListItemName> Items
    {
        get
        {
            if (m_items != null && ItemsArray != null && m_items.Except(ItemsArray).Any())
            {
            m_items = new ObservableCollection<ListItemName>(ItemsArray);
            }
            return m_items;
        }
        set
        {
            m_items = value;
            ItemsArray = new ListItemName[m_items.Count];
            for (int i = 0; i < m_items.Count; i++)
            {
                ItemsArray[i] = m_items[i];
            }
        }
    }

[XmlChoiceIdentifier("ItemTypeArray")]
    [XmlElement(ElementName = "Item", Type = typeof(ObservableCollection<ListItemName>))]
    [XmlElement(ElementName = "Macro", Type = typeof(ObservableCollection<ListItemName>))]
    public ListItemName[] ItemsArray
    {
        get { return m_itemsArray; }
        set { m_itemsArray = value; }
    }


    public GroupAndItemsCollection()
    {
        //to expand nodes in XamDataTree
        IsExpanded = true;

        Items = new ObservableCollection<ListItemName>();
        Items.CollectionChanged += Items_CollectionChanged;
    }

    void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        ItemsArray = new ListItemName[m_items.Count];
        for (int i = 0; i < m_items.Count; i++)
        {
            ItemsArray[i] = m_items[i];
        }
    }
}

然后在我的main方法中,我尝试通过执行以下操作来序列化:

using (StreamWriter writer = new StreamWriter(dlg.FileName))
                    {
                        ItemChoiceType[] ic = new ItemChoiceType[]
                        {
                            ItemChoiceType.Item, 
                            ItemChoiceType.Macro
                        };
                        XmlSerializer xml = null;

                                group.ItemTypeArray = ic;
                            xml = new XmlSerializer(typeof(GroupAndItemsCollection));
                            xml.Serialize(writer, group);



                        writer.Close();
                    }

使用此解决方案,我收到以下错误:

System.InvalidOperationException occurred


HResult=-2146233079
  Message=There was an error generating the XML document.
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
       at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces)
       at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o)
       at Otometrics.ICSSuite.Reports.ViewModel.EditReportVM.<InitializeCommands>b__38(Object o) in 
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=Invalid or missing value of the choice identifier 'ItemTypeArray' of type 'ItemChoiceType[]'.
       Source=Microsoft.GeneratedCode
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCustomReportList.Write4_GroupAndItemsCollection(String n, String ns, GroupAndItemsCollection o, Boolean isNullable, Boolean needType)

现在,如果我选择忽略尝试同步数组和可观察集合,序列化可以工作......下面的代码序列化就好了。

[XmlType(IncludeInSchema = false)]
public enum ItemChoiceType
{
    [XmlEnumAttribute("Item")]
    Item,
    [XmlEnumAttribute("Macro")]
    Macro
}

[Serializable()]
public class GroupAndItemsCollection
{
    [XmlElementAttribute(IsNullable = false)]
    [XmlIgnore]
    public ItemChoiceType[] ItemTypeArray;

    [XmlAttribute(AttributeName = "name")]
    public string Group
    {
        get { return m_Group; }
        set
        {
            if (m_Group == value)
                return;
            m_Group = value;
            //OnPropertyChanged("Group");
        }
    }

    private ListItemName[] m_itemsArray;

[XmlChoiceIdentifier("ItemTypeArray")]
    [XmlElement(ElementName = "Item", Type = typeof(ObservableCollection<ListItemName>))]
    [XmlElement(ElementName = "Macro", Type = typeof(ObservableCollection<ListItemName>))]
    public ListItemName[] ItemsArray
    {
        get { return m_itemsArray; }
        set { m_itemsArray = value; }
    }


    public GroupAndItemsCollection()
    {
        IsExpanded = true;
    }
}

那么我之前的例子是什么让XmlSerializer像这样失败:

Message=Invalid or missing value of the choice identifier 'ItemTypeArray' of type 'ItemChoiceType[]'.

2 个答案:

答案 0 :(得分:0)

虽然有一些关于此错误消息的答案是正确的。他们都没有工作。我希望我能够获得荣誉,但是,我真正聪明的团队领导才能理解。我的代码发生了什么,我们使用xsd2code为具有xmlChoiceIdentifier的模式生成vb。发生的事情是,在我们的业务类中,当我们循环遍历代码时,ItemChoiceType的对象在循环之外。因此,当它验证xml时,第一个节点是好的,之后的每个节点都不好。虽然我有一个具有良好值的ItemsElementName,但它只有一次迭代,其余的xml验证将因此错误而失败。

我们在创建xml和Viola时将ItemsChoiceType移动到循环中!希望这可以帮助。它可能与此Stack Overflow中的修复无关,但它给出了相同的错误,如果您的问题与我们的相同。您将看到此页面。

快乐编码:)

答案 1 :(得分:0)

使用时的问题![xsd2code与枚举节点有关。是的,它读取第一个节点,然后在其他节点上失败。对我来说,一旦我将GenerateOrderXmlAttributes和GenerateXMLAttributes更改为true并将CollectionObjectType更改为Array,它就可以工作。