Remove reflection use in XmlWriterHelper

This commit is contained in:
Sergio Pedri 2022-05-11 04:38:29 +02:00
Родитель e929ee953e
Коммит 736fc281d5
1 изменённых файлов: 24 добавлений и 164 удалений

Просмотреть файл

@ -3,20 +3,15 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#if WINDOWS_UWP
#endif
using System.Xml;
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal static class XmlWriterHelper
{
public static void Write(System.Xml.XmlWriter writer, object element)
public static void Write(XmlWriter writer, object element)
{
// If it isn't an XML element, don't write anything
if (element is not IHaveXmlName xmlElement)
@ -26,56 +21,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
writer.WriteStartElement(xmlElement.Name);
IEnumerable<PropertyInfo> properties = GetProperties(element.GetType());
List<object> elements = new List<object>();
object content = null;
// Write the attributes first
foreach (PropertyInfo p in properties)
{
IEnumerable<Attribute> attributes = GetCustomAttributes(p);
NotificationXmlAttributeAttribute attr = attributes.OfType<NotificationXmlAttributeAttribute>().FirstOrDefault();
object propertyValue = GetPropertyValue(p, element);
// If it's the additional properties item
if (p.Name == nameof(IHaveXmlAdditionalProperties.AdditionalProperties) && element is IHaveXmlAdditionalProperties && p.PropertyType == typeof(IReadOnlyDictionary<string, string>))
{
continue;
}
// If it's an attribute
else if (attr != null)
{
continue;
}
// If it's a content attribute
else if (attributes.OfType<NotificationXmlContentAttribute>().Any())
{
continue;
}
else if (p.Name == nameof(IHaveXmlChildren.Children) && element is IHaveXmlChildren && p.PropertyType == typeof(IEnumerable<object>))
{
continue;
}
// Otherwise it's an element or collection of elements
else
{
continue;
}
}
content = (element as IHaveXmlText)?.Text;
foreach (var property in (element as IHaveXmlAdditionalProperties)?.AdditionalProperties ?? Enumerable.Empty<KeyValuePair<string, string>>())
{
writer.WriteAttributeString(property.Key, property.Value);
}
// Write all named properties
foreach (var property in (element as IHaveXmlNamedProperties)?.EnumerateNamedProperties() ?? Enumerable.Empty<KeyValuePair<string, object>>())
{
if (property.Value is not null)
@ -84,123 +30,37 @@ namespace Microsoft.Toolkit.Uwp.Notifications
}
}
// Write all additional properties
foreach (var property in (element as IHaveXmlAdditionalProperties)?.AdditionalProperties ?? Enumerable.Empty<KeyValuePair<string, string>>())
{
writer.WriteAttributeString(property.Key, property.Value);
}
// Write the inner text, if any
if ((element as IHaveXmlText)?.Text is string { Length: > 0 } text)
{
writer.WriteString(text);
}
// Write all children, if any
foreach (var child in (element as IHaveXmlChildren)?.Children ?? Enumerable.Empty<object>())
{
elements.Add(child);
}
// Then write children
foreach (object el in elements)
{
// Otherwise just write the single element
Write(writer, el);
}
// Then write any content if there is content
if (content != null)
{
string contentString = content.ToString();
if (!string.IsNullOrWhiteSpace(contentString))
{
writer.WriteString(contentString);
}
Write(writer, child);
}
writer.WriteEndElement();
}
private static object GetPropertyValue(PropertyInfo propertyInfo, object obj)
{
#if NETFX_CORE
return propertyInfo.GetValue(obj);
#else
return propertyInfo.GetValue(obj, null);
#endif
}
private static string PropertyValueToString(object propertyValue)
{
Type type = propertyValue.GetType();
if (IsEnum(type))
return propertyValue switch
{
EnumStringAttribute enumStringAttr = GetEnumStringAttribute(propertyValue as Enum);
if (enumStringAttr != null)
{
return enumStringAttr.String;
}
}
else if (propertyValue is bool)
{
if ((bool)propertyValue)
{
return "true";
}
return "false";
}
else if (propertyValue is DateTimeOffset?)
{
DateTimeOffset? dateTime = propertyValue as DateTimeOffset?;
if (dateTime.HasValue)
{
// ISO 8601 format
return System.Xml.XmlConvert.ToString(dateTime.Value);
}
else
{
return null;
}
}
return propertyValue.ToString();
}
private static EnumStringAttribute GetEnumStringAttribute(Enum enumValue)
{
#if NETFX_CORE
return enumValue.GetType().GetTypeInfo().GetDeclaredField(enumValue.ToString()).GetCustomAttribute<EnumStringAttribute>();
#else
MemberInfo[] memberInfo = enumValue.GetType().GetMember(enumValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(EnumStringAttribute), false);
if (attrs != null && attrs.Length > 0)
return attrs[0] as EnumStringAttribute;
}
return null;
#endif
}
private static bool IsEnum(Type type)
{
#if NETFX_CORE
return type.GetTypeInfo().IsEnum;
#else
return type.IsEnum;
#endif
}
private static IEnumerable<PropertyInfo> GetProperties(Type type)
{
#if NETFX_CORE
return type.GetTypeInfo().DeclaredProperties;
#else
return type.GetProperties();
#endif
}
private static IEnumerable<Attribute> GetCustomAttributes(PropertyInfo propertyInfo)
{
#if NETFX_CORE
return propertyInfo.GetCustomAttributes();
#else
return propertyInfo.GetCustomAttributes(true).OfType<Attribute>();
#endif
true => "true",
false => "false",
DateTimeOffset dateTime => XmlConvert.ToString(dateTime), // ISO 8601 format
{ } value => value.ToString(),
_ => null
};
}
/// <summary>