diff --git a/Gu.Xml.Tests/XmlTests.Properties.cs b/Gu.Xml.Tests/XmlTests.Properties.cs index ab2f54e..3df2a0c 100644 --- a/Gu.Xml.Tests/XmlTests.Properties.cs +++ b/Gu.Xml.Tests/XmlTests.Properties.cs @@ -85,6 +85,30 @@ public void XmlIgnoreAttribute() Assert.AreEqual(expected, actual); } + [Test] + public void XmlAttributeAttribute() + { + var with = new WithXmlAttribute { Value = 1 }; + var expected = "" + Environment.NewLine + + "" + Environment.NewLine + + ""; + + var actual = Xml.Serialize(with); + Assert.AreEqual(expected, actual); + } + + [Test] + public void XmlAttributeAttributeExplicitName() + { + var with = new WithXmlAttributeExplicitName { Value = 1 }; + var expected = "" + Environment.NewLine + + "" + Environment.NewLine + + ""; + + var actual = Xml.Serialize(with); + Assert.AreEqual(expected, actual); + } + public class WithGetSet { public int Value { get; set; } @@ -128,6 +152,18 @@ public class WithXmlElement public int Value { get; set; } } + public class WithXmlAttribute + { + [XmlAttribute] + public int Value { get; set; } + } + + public class WithXmlAttributeExplicitName + { + [XmlAttribute("Name")] + public int Value { get; set; } + } + public class WithXmlIgnore { [XmlIgnore] diff --git a/Gu.Xml/Writers/AttributeWriter.cs b/Gu.Xml/Writers/AttributeWriter.cs index b4076ea..c56f08e 100644 --- a/Gu.Xml/Writers/AttributeWriter.cs +++ b/Gu.Xml/Writers/AttributeWriter.cs @@ -3,6 +3,7 @@ using System; using System.IO; using System.Reflection; + using System.Xml.Serialization; public abstract class AttributeWriter { @@ -13,12 +14,20 @@ public AttributeWriter(string name) public string Name { get; } - public static AttributeWriter Create(string name, PropertyInfo property) + public static bool TryCreate(PropertyInfo property, out AttributeWriter writer) { - return (AttributeWriter)typeof(AttributeWriter) - .GetMethod(nameof(CreateWriter), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(property.ReflectedType, property.PropertyType) - .Invoke(null, new object[] { name, property }); + if (Attribute.GetCustomAttribute(property, typeof(XmlAttributeAttribute)) is XmlAttributeAttribute attribute) + { + var name = string.IsNullOrEmpty(attribute.AttributeName) ? property.Name : attribute.AttributeName; + writer = (AttributeWriter)typeof(AttributeWriter) + .GetMethod(nameof(CreateWriter), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod(property.ReflectedType, property.PropertyType) + .Invoke(null, new object[] { name, property }); + return true; + } + + writer = null; + return false; } public abstract void Write(TextWriter writer, T source); diff --git a/Gu.Xml/Writers/AttributeWriter{TSource,TValue}.cs b/Gu.Xml/Writers/AttributeWriter{TSource,TValue}.cs index 056b260..4a4a64f 100644 --- a/Gu.Xml/Writers/AttributeWriter{TSource,TValue}.cs +++ b/Gu.Xml/Writers/AttributeWriter{TSource,TValue}.cs @@ -21,6 +21,7 @@ public override void Write(TextWriter writer, T source) { if (SimpleValueWriter.TryGet(value, out var valueWriter)) { + writer.Write(" "); writer.Write(this.Name); writer.Write("=\""); valueWriter.Write(writer, value); diff --git a/Gu.Xml/Writers/ComplexValueWriter.cs b/Gu.Xml/Writers/ComplexValueWriter.cs index 0f98fab..e69fa10 100644 --- a/Gu.Xml/Writers/ComplexValueWriter.cs +++ b/Gu.Xml/Writers/ComplexValueWriter.cs @@ -31,9 +31,20 @@ public static ComplexValueWriter GetOrCreate(T value) private static ComplexValueWriter Create(Type type) { return new ComplexValueWriter( - Array.Empty(), + Attributes().ToArray(), Elements().ToArray()); + IEnumerable Attributes() + { + foreach (var property in type.GetProperties()) + { + if (AttributeWriter.TryCreate(property, out var writer)) + { + yield return writer; + } + } + } + IEnumerable Elements() { foreach (var property in type.GetProperties()) diff --git a/Gu.Xml/XmlWriter.cs b/Gu.Xml/XmlWriter.cs index 09d469d..347535c 100644 --- a/Gu.Xml/XmlWriter.cs +++ b/Gu.Xml/XmlWriter.cs @@ -1,6 +1,7 @@ namespace Gu.Xml { using System; + using System.Collections.Generic; using System.IO; /// @@ -40,7 +41,7 @@ public void WriteElement(string name, T value) } else if (ComplexValueWriter.GetOrCreate(value) is ComplexValueWriter complex) { - this.WriteStartElement(name); + this.WriteStartElement(name, value, complex.Attributes); this.writer.WriteLine(); foreach (var elementWriter in complex.Elements) { @@ -69,6 +70,20 @@ public void WriteStartElement(string name) this.indentLevel++; } + public void WriteStartElement(string name, T source, IReadOnlyList attributeWriters) + { + this.WriteIndentation(); + this.writer.Write("<"); + this.writer.Write(name); + foreach (var attributeWriter in attributeWriters) + { + attributeWriter.Write(this.writer, source); + } + + this.writer.Write(">"); + this.indentLevel++; + } + public void WriteEndElement(string name) { this.writer.Write("