.NET XML序列化错误:选择标识符的值无效或丢失
本文关键字:无效 标识符 序列化 XML 错误 选择 NET | 更新日期: 2023-09-27 18:21:19
以下说明来自:
.NET XML序列化错误(存在反映类型的错误)
基于XmlChoiceIdentifier 创建对象
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlchoiceidentifierattribute(v=vs.110).aspx
我尝试使用XmlChoiceIdentifier属性序列化对象数组。但显然序列化程序需要一个数组,而ObservableCollection将导致序列化程序抛出并出错(第一个链接)。我真的需要一个ObservableCollection来保持UI的更新。因此,我试图让序列化引擎访问数组,而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];
}
}
}
然后在我的主要方法中,我尝试通过以下操作进行序列化:
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[]'.
尽管有一些关于此错误消息的答案是正确的。它们都不起作用。我希望我能获得荣誉,但遗憾的是,我真正聪明的团队领导发现了这一点。我的代码中发生的事情是,我们使用xsd2code为具有xmlChoiceIdentifier的模式生成vb。发生的情况是,在我们的业务类中,当我们循环代码时,ItemChoiceType的对象在循环之外。因此,在验证xml时,第一个节点是好的,之后的每个节点都不好。尽管我有一个ItemsElementName值很好,但它只是一次迭代,其余的xml验证都将失败,并出现此错误。
在创建xml和Viola时,我们在循环中移动了ItemsChoiceType!希望这能有所帮助。它可能与此堆栈溢出中的修复程序无关,但它给出了相同的错误,如果您的问题与我们的问题相同。您将看到此页面。
快乐编码:)
使用时的问题![xsd2code与节点的枚举有关。是的,它读取第一个节点,然后在其他节点上失败。对我来说,一旦我将GenerateOrderXmlAttributes和GenerateXMLAttributes更改为true,并将CollectionObjectType更改为Array.