C# XML десериализация
Вытаскиваю мои волосы снова. Я весь день смотрел на это и не могу понять, возможно ли это или нет, или что я делаю не так.
Я создал коллекцию пользовательских объектов.
public class ObjectCollection<T> : IEnumerable<T>, IEnumerable where T : IUniqueObjectIdentifier
{
protected List<T> List = new List<T>();
protected Dictionary<Guid, int> Keys = new Dictionary<Guid, int>();
protected Dictionary<int, Guid> Inverse = new Dictionary<int, Guid>();
protected Dictionary<string, Guid> Name = new Dictionary<string, Guid>();
public void Add(T item)
{
if (item is IUniqueObjectIdentifier itemIdentifier)
if (!Keys.ContainsKey(itemIdentifier.Id))
{
List.Add(item);
Keys.Add(itemIdentifier.Id, List.IndexOf(item));
Inverse.Add(List.IndexOf(item), itemIdentifier.Id);
}
}
public void Remove(T item)
{
if (item is IUniqueObjectIdentifier itemIdentifier)
if (List.Contains(item))
{
int index = List.IndexOf(item);
Guid key = Inverse[index];
Keys.Remove(itemIdentifier.Id);
Inverse.Remove(index);
List.Remove(item);
}
}
public void Remove(int index)
{
if (index < List.Count)
{
Guid key = Inverse[index];
Keys.Remove(key);
List.RemoveAt(index);
Inverse.Remove(index);
}
}
public void Remove(Guid key)
{
if (Keys.ContainsKey(key))
{
int index = Keys[key];
Keys.Remove(key);
List.RemoveAt(index);
Inverse.Remove(index);
}
}
public void Clear()
{
Keys.Clear();
List.Clear();
Inverse.Clear();
}
public int Count => List.Count;
public bool Contains(T item)
{
return List.Contains(item);
}
public bool ContainsKey(Guid key)
{
return Keys.ContainsKey(key);
}
public T this[int index]
{
get
{
if (index < List.Count)
return List[index];
else
return default(T);
}
}
public T this[Guid key]
{
get
{
if (Keys.ContainsKey(key))
return List[Keys[key]];
else
return default(T);
}
}
public IEnumerator<T> GetEnumerator()
{
return List.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{ return List.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator()
{
return List.GetEnumerator();
}
У меня тогда есть вещь:
public class Thing
{
//Collections
[XmlElement(ElementName = "Fields")]
public Fields Fields { get; set; }
Объект Fields наследуется от ObjectCollection:
[XmlRoot(ElementName = "Field")]
public class Fields:ObjectCollection<Field>
{
}
Наконец, у меня есть класс поля, который содержит целый набор свойств:
[XmlRoot(ElementName = "Field")]
public class Field : IUniqueObjectIdentifier
{
[XmlElement(ElementName = "FLAGS")]
public int Flags{ get; set; }
Единственный способ, которым это, кажется, работает, если я создаю свой класс полей следующим образом:
[XmlRoot(ElementName = "Fields")]
public class Fields
{
[XmlElement(ElementName = "Field")] private List<Field> Items { get; set; }
}
Который я ненавижу. Необходим доступ к нему, например, Thing.Fields.Items.Add, а не Thing.Fields.Add. не имеет смысла для меня.
XML выглядит так:
<Thing ID="BD825D4AD7F44C00B41E8827646EE196" Name="Thingy">
<Fields>
<Field ID="02A5DA70FD94495E963DA5D7E414E30B" NAME="Fieldy">
<FLAGS>1</FLAGS>
</Field>
<Field ID="DAF609FFD05B413F9F9D0DA8DD241CB3" NAME="Fieldy2">
<FLAGS>1</FLAGS>
Когда я пытаюсь десериализовать его, я просто получаю поле Default, то есть оно добавляет к объектной коллекции только один элемент, и очевидно, что не удалось десериализовать поле, поскольку оно по существу пустое.
Я пытался выяснить, могу ли я выяснить, какие атрибуты могут помочь, но я не уверен. Я также посмотрел на создание собственной десериализации, но это кажется излишним.
Может ли кто-нибудь помочь направить меня в правильном направлении. Я просто хочу аккуратное и опрятное решение - с наименьшим количеством сложности!!! Как и все мы:-)
Любая помощь будет высоко ценится, прежде чем я спрыгну с местного пирса.
Ура,
Стю.
1 ответ
Хорошо, я немного упростил пример в своем посте из:
<Thing ID="BD825D4AD7F44C00B41E8827646EE196" Name="Thingy">
<Fields>
<AField ID="02A5DA70FD94495E963DA5D7E414E30B" NAME="Fieldy">
<FLAGS>1</FLAGS>
</AField>
<AField ID="DAF609FFD05B413F9F9D0DA8DD241CB3" NAME="Fieldy2">
<FLAGS>1</FLAGS>
чтобы:
<Thing ID="BD825D4AD7F44C00B41E8827646EE196" Name="Thingy">
<Fields>
<Field ID="02A5DA70FD94495E963DA5D7E414E30B" NAME="Fieldy">
<FLAGS>1</FLAGS>
</Field>
<Field ID="DAF609FFD05B413F9F9D0DA8DD241CB3" NAME="Fieldy2">
<FLAGS>1</FLAGS>
А ТАКЖЕ:
[XmlRoot(ElementName = "AField")]
public class Fields:ObjectCollection<Field>
{
}
Для того, чтобы:
[XmlRoot(ElementName = "Field")]
public class Fields:ObjectCollection<Field>
{
}
Ответ в том, что ДАЖЕ, ЧЕМ вы указываете корень, он не будет автоматически корректно отображаться на объекте; ВАМ НУЖНО УКАЗАТЬ ЕГО [XmlType("AField")], очевидно, если они не совпадают. В размещенном случае: XmlRoot(ElementName = "Field")] = <Field ID="02A5DA70FD94495E963DA5D7E414E30B" NAME="Fieldy">
Так что это работает:
[XmlRoot(ElementName = "AField")]
[XmlType("AField")]
public class Fields:ObjectCollection<Field>
{
}
Уроки выучены:
- Не просто ваши примеры; опубликовать их как есть!
- Если у вас есть проблема, разбейте ее на малейшие действия, чтобы преодолеть ее.
Я не могу не чувствовать, что это немного задом наперед, учитывая тот факт, что вы сопоставили его с корневым элементом, но эй. Благодаря dbc в их помощи с этим, или я чувствую, что был бы на дне моря. Проголосовал за явное усилие.
Уф!
Стю.