Remove reflection use in XmlWriterHelper
This commit is contained in:
Родитель
e929ee953e
Коммит
736fc281d5
|
@ -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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче