问题
I would like to know how to ignore a specific item/index of a List<T>
from being serialized using XmlSerializer
.
For example, consider the following list:
...
List<int> collection = new List<int>() {0, 1, 2};
...
What I would like to achieve is when serializing the above List<int>
using XmlSerializer
, I want the 0
to be ignored from being serialized, so the desired result is:
...
<collection>
<int>1</int>
<int>2</int>
</collection> // as you can see - there is no <int>0</int> value.
...
Thanks.
UPDATE
The following code is a concrete example of my question:
[Serializable]
public class Ball
{
private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(Ball));
public Ball()
{
// value 1 is a default value which I don't want to be serialized.
Points = new List<int>() { 1 };
IsEnabled = false;
}
public List<int> Points { get; set; }
public bool IsEnabled { get; set; }
public void Save()
{
using (StreamWriter writer = new StreamWriter(FILENAME))
{
Serializer.Serialize(writer, this);
}
}
public Ball Load()
{
using (StreamReader reader = new StreamReader(FILENAME))
{
return (Ball)Serializer.Deserialize(reader);
}
}
}
回答1:
I suspect you are actually trying to solve an XY problem where the real problem is the one described in the question Deserializing List with XmlSerializer Causing Extra Items: when you serialize and deserialize a collection property that has default items added in the constructor, the default items get duplicated, because the deserialized default items get added to the latest default items.
That answer to that question provides one workaround, namely to move initialization of the default collection entries out of the constructor. If that's not convenient, you can instead introduce a proxy array property and serialize that instead of the underlying collection:
[Serializable]
public class Ball
{
public Ball()
{
Points = new List<int>() { 1 };
IsEnabled = false;
}
public bool IsEnabled { get; set; }
[XmlIgnore]
public List<int> Points { get; set; }
[XmlArray("Points")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
public int[] SerializablePoints
{
get
{
return (Points == null ? null : Points.ToArray());
}
set
{
Points = ListExtensions.Initialize(Points, value);
}
}
}
public static class ListExtensions
{
public static List<T> Initialize<T>(List<T> list, T[] value)
{
if (value == null)
{
if (list != null)
list.Clear();
}
else
{
(list = list ?? new List<T>(value.Length)).Clear();
list.AddRange(value);
}
return list;
}
}
For an explanation of why the property must be an array, see XML Deserialization of collection property with code defaults.
回答2:
Better solution is to create a new collection with LINQ query and pass to serializer, like
List<int> collection = new List<int>(){ 0, 1, 2, 3 };
using (var fs = new StreamWriter("serialized.txt"))
{
XmlSerializer serializer = new XmlSerializer(collection.GetType());
serializer.Serialize(fs, collection.Where(x => x != 0).ToList());
}
来源:https://stackoverflow.com/questions/33786527/how-to-ignore-a-specific-listt-item-when-serializing-a-container-class