forked from tsai/mathnet-numerics
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.5 KiB
111 lines
3.5 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
using System.Xml.Schema;
|
|
using System.Xml.Serialization;
|
|
using NUnit.Framework;
|
|
|
|
namespace MathNet.Numerics.Tests.Spatial
|
|
{
|
|
|
|
#if !NETCOREAPP1_1
|
|
|
|
public class AssertXmlTests
|
|
{
|
|
[Test]
|
|
public void XmlSerializerRoundTripTest()
|
|
{
|
|
var dummy = new XmlSerializableDummy("Meh", 14);
|
|
var roundTrip = AssertXml.XmlSerializerRoundTrip(dummy, @"<XmlSerializableDummy Age=""14""><Name>Meh</Name></XmlSerializableDummy>");
|
|
Assert.AreEqual(dummy.Name, roundTrip.Name);
|
|
Assert.AreEqual(dummy.Age, roundTrip.Age);
|
|
}
|
|
|
|
public class XmlSerializableDummy : IXmlSerializable
|
|
{
|
|
private readonly string name;
|
|
|
|
public XmlSerializableDummy(string name, int age)
|
|
{
|
|
this.Age = age;
|
|
this.name = name;
|
|
}
|
|
|
|
// ReSharper disable once UnusedMember.Local
|
|
private XmlSerializableDummy()
|
|
{
|
|
}
|
|
|
|
public string Name => this.name;
|
|
|
|
public int Age { get; set; }
|
|
|
|
public XmlSchema GetSchema() => null;
|
|
|
|
public void ReadXml(XmlReader reader)
|
|
{
|
|
var e = (XElement)XNode.ReadFrom(reader);
|
|
this.Age = XmlConvert.ToInt32(e.Attribute("Age").Value);
|
|
var name = ReadAttributeOrElement(e, "Name");
|
|
WriteValueToReadonlyField(this, name, () => this.name);
|
|
}
|
|
|
|
public void WriteXml(XmlWriter writer)
|
|
{
|
|
writer.WriteAttributeString("Age", this.Age.ToString(CultureInfo.InvariantCulture));
|
|
writer.WriteElementString("Name", this.Name);
|
|
}
|
|
|
|
private static string ReadAttributeOrElement(XElement e, string localName)
|
|
{
|
|
XAttribute xattribute = e.Attributes()
|
|
.SingleOrDefault(x => x.Name.LocalName == localName);
|
|
if (xattribute != null)
|
|
{
|
|
return xattribute.Value;
|
|
}
|
|
|
|
XElement xelement = e.Elements()
|
|
.SingleOrDefault(x => x.Name.LocalName == localName);
|
|
if (xelement != null)
|
|
{
|
|
return xelement.Value;
|
|
}
|
|
|
|
throw new XmlException($"Attribute or element {localName} not found");
|
|
}
|
|
|
|
private static void WriteValueToReadonlyField<TClass, TProperty>(
|
|
TClass item,
|
|
TProperty value,
|
|
Expression<Func<TProperty>> fieldExpression)
|
|
{
|
|
string name = ((MemberExpression)fieldExpression.Body).Member.Name;
|
|
GetAllFields(item.GetType())
|
|
.Single(x => x.Name == name)
|
|
.SetValue(item, value);
|
|
}
|
|
|
|
private static IEnumerable<FieldInfo> GetAllFields(Type t)
|
|
{
|
|
if (t == null)
|
|
{
|
|
return Enumerable.Empty<FieldInfo>();
|
|
}
|
|
|
|
BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static |
|
|
BindingFlags.Public | BindingFlags.NonPublic;
|
|
return t.GetFields(bindingAttr)
|
|
.Concat(GetAllFields(t.BaseType));
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|