Can any one explain to me what is happening here and why one test passes while the other fails?
The only difference between the two XmlRoots
is the dirrection of the property delegation... Bug? or have i missed something?
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
using Documation.Purchasing.Domain.Configurables.Controls;
using NUnit.Framework;
namespace FruitTests
{
[TestFixture]
public class FruitTests
{
[Test]
public void Fruit_Fail()
{
// Fails
AssertFruitDeserialized<FailingFruitRoot>();
}
[Test]
public void Fruit_Win()
{
// Passes
AssertFruitDeserialized<WinningFruitRoot>();
}
private static void AssertFruitDeserialized<TFruitRoot>()
where TFruitRoot : IFruitCollection
{
var ser = new XmlSerializer(typeof(TFruitRoot));
var xml =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<fruits>
<fruit name=""Apple"" />
<fruit name=""Banana"" />
<fruit name=""Cherry"" />
</fruits>";
using (var stringReader = new StringReader(xml))
{
var fruit = (IFruitCollection)ser.Deserialize(stringReader);
Assert.AreEqual(3, fruit.ListFruits?.Count(), "ListFruits didn't contain the right number of values");
Assert.AreEqual(3, fruit.Fruits?.Count(), "Fruits didn't contain the right number of values");
}
}
private interface IFruitCollection
{
IDictionary<string, Fruit> Fruits { get; }
List<Fruit> ListFruits { get; }
}
[XmlRoot("fruits")]
public class WinningFruitRoot : IFruitCollection
{
[XmlIgnore]
public IDictionary<string, Fruit> Fruits
{
get { return this.ListFruits?.ToDictionary(f => f.Name); }
set { this.ListFruits = value?.Values.ToList(); }
}
[XmlElement("fruit")]
public List<Fruit> ListFruits { get; set; }
}
[XmlRoot("fruits")]
public class FailingFruitRoot : IFruitCollection
{
[XmlIgnore]
public IDictionary<string, Fruit> Fruits { get; set; }
[XmlElement("fruit")]
public List<Fruit> ListFruits
{
get { return this.Fruits?.Values.ToList(); }
set { this.Fruits = value?.ToDictionary(f => f.Name); }
}
}
public class Fruit
{
[XmlAttribute("name")]
public string Name { get; set; }
}
}
}