Implement caching and extension methods
This commit is contained in:
1 parent
2452306e6c
commit
9aa9ff9291
1 file changed
+80
-27
@@ -25,6 +25,8 @@ namespace VocaluxeLib.Xml
|
|||||||
{
|
{
|
||||||
public string Name;
|
public string Name;
|
||||||
public FieldInfo Info;
|
public FieldInfo Info;
|
||||||
|
public object DefaultValue;
|
||||||
|
public bool HasDefaultValue;
|
||||||
public bool IsList; //List with child elements (<List><El/><El/></List>)
|
public bool IsList; //List with child elements (<List><El/><El/></List>)
|
||||||
public bool IsEmbeddedList; //List w/o child elements(<List/><List/>)
|
public bool IsEmbeddedList; //List w/o child elements(<List/><List/>)
|
||||||
public bool IsNullable;
|
public bool IsNullable;
|
||||||
@@ -79,67 +81,119 @@ namespace VocaluxeLib.Xml
|
|||||||
}
|
}
|
||||||
#endregion Debug Helpers
|
#endregion Debug Helpers
|
||||||
|
|
||||||
private static bool _HasAttribute(this FieldInfo field, Type attributeType)
|
private static bool _HasAttribute<T>(this FieldInfo field)
|
||||||
{
|
{
|
||||||
return field.GetCustomAttributes(attributeType, false).Length > 0;
|
return field.GetCustomAttributes(typeof(T), false).Length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static T _GetAttribute<T>(this ICustomAttributeProvider field) where T : class
|
||||||
|
{
|
||||||
|
object[] attributes = field.GetCustomAttributes(typeof(T), false);
|
||||||
|
return attributes.Length == 0 ? null : (T)attributes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool _IsList(this Type type)
|
||||||
|
{
|
||||||
|
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool _IsList(this FieldInfo field)
|
||||||
|
{
|
||||||
|
return field.FieldType._IsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<Type, List<SFieldInfo>> _CacheFieldAttributes = new Dictionary<Type, List<SFieldInfo>>();
|
||||||
|
private static readonly Dictionary<Type, List<SFieldInfo>> _CacheFieldFields = new Dictionary<Type, List<SFieldInfo>>();
|
||||||
|
private static readonly Dictionary<Type, String> _CacheTypeName = new Dictionary<Type, string>();
|
||||||
|
|
||||||
private static List<SFieldInfo> _GetFields(Type type, bool attributes)
|
private static List<SFieldInfo> _GetFields(Type type, bool attributes)
|
||||||
{
|
{
|
||||||
List<SFieldInfo> result = new List<SFieldInfo>();
|
List<SFieldInfo> result;
|
||||||
|
if (attributes && _CacheFieldAttributes.TryGetValue(type, out result) ||
|
||||||
|
!attributes && _CacheFieldFields.TryGetValue(type, out result))
|
||||||
|
return result;
|
||||||
|
result = new List<SFieldInfo>();
|
||||||
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||||
foreach (FieldInfo field in fields)
|
foreach (FieldInfo field in fields)
|
||||||
{
|
{
|
||||||
if (field._HasAttribute(typeof(XmlIgnoreAttribute)))
|
if (field._HasAttribute<XmlIgnoreAttribute>())
|
||||||
continue;
|
continue;
|
||||||
object[] attElement = field.GetCustomAttributes(typeof(XmlAttributeAttribute), false);
|
XmlAttributeAttribute attribute = field._GetAttribute<XmlAttributeAttribute>();
|
||||||
if (attElement.Length > 0 != attributes)
|
if (attribute != null != attributes)
|
||||||
continue;
|
continue;
|
||||||
SFieldInfo info = new SFieldInfo {Info = field};
|
SFieldInfo info = new SFieldInfo {Info = field};
|
||||||
if (attElement.Length > 0)
|
if (attribute != null)
|
||||||
info.Name = ((XmlAttributeAttribute)attElement[0]).AttributeName;
|
info.Name = attribute.AttributeName;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attElement = field.GetCustomAttributes(typeof(XmlElementAttribute), false);
|
XmlElementAttribute element = field._GetAttribute<XmlElementAttribute>();
|
||||||
if (attElement.Length > 0)
|
if (element != null)
|
||||||
info.Name = ((XmlElementAttribute)attElement[0]).ElementName;
|
info.Name = element.ElementName;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XmlArrayAttribute array = field._GetAttribute<XmlArrayAttribute>();
|
||||||
|
if (array != null)
|
||||||
|
{
|
||||||
|
Debug.Assert(field._IsList());
|
||||||
|
info.Name = array.ElementName;
|
||||||
|
info.IsList = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (string.IsNullOrEmpty(info.Name))
|
if (string.IsNullOrEmpty(info.Name))
|
||||||
info.Name = field.Name;
|
info.Name = field.Name;
|
||||||
|
|
||||||
if (field.FieldType.IsGenericType)
|
if (field.FieldType.IsGenericType)
|
||||||
{
|
{
|
||||||
if (field.FieldType.GetGenericTypeDefinition() == typeof(List<>))
|
if (field._IsList())
|
||||||
{
|
{
|
||||||
attElement = field.GetCustomAttributes(typeof(XmlArrayAttribute), false);
|
if (!info.IsList)
|
||||||
if (attElement.Length > 0)
|
{
|
||||||
info.IsList = true;
|
Debug.Assert(!field._HasAttribute<XmlArrayAttribute>(), "A field cannot have an XmlElement- and XmlArray-Attribute");
|
||||||
else
|
|
||||||
info.IsEmbeddedList = true;
|
info.IsEmbeddedList = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (field.FieldType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
else if (field.FieldType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||||
info.IsNullable = true;
|
info.IsNullable = true;
|
||||||
info.SubType = field.FieldType.GetGenericArguments()[0];
|
info.SubType = field.FieldType.GetGenericArguments()[0];
|
||||||
}
|
}
|
||||||
if (field._HasAttribute(typeof(XmlNormalizedAttribute)))
|
if (field._HasAttribute<XmlNormalizedAttribute>())
|
||||||
{
|
{
|
||||||
Debug.Assert(field.FieldType == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized");
|
Debug.Assert(field.FieldType == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized");
|
||||||
info.IsNormalized = true;
|
info.IsNormalized = true;
|
||||||
}
|
}
|
||||||
|
DefaultValueAttribute defAttr = field._GetAttribute<DefaultValueAttribute>();
|
||||||
|
if (defAttr != null)
|
||||||
|
{
|
||||||
|
Debug.Assert(!field._IsList(), "Lists cannot have a default value");
|
||||||
|
info.HasDefaultValue = true;
|
||||||
|
info.DefaultValue = defAttr.Value;
|
||||||
|
}
|
||||||
result.Add(info);
|
result.Add(info);
|
||||||
}
|
}
|
||||||
|
if (attributes)
|
||||||
|
_CacheFieldAttributes.Add(type, result);
|
||||||
|
else
|
||||||
|
_CacheFieldFields.Add(type, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string _GetTypeName(Type type)
|
private static string _GetTypeName(Type type)
|
||||||
{
|
{
|
||||||
object[] att = type.GetCustomAttributes(typeof(XmlTypeAttribute), false);
|
string name;
|
||||||
if (att.Length > 0)
|
if (_CacheTypeName.TryGetValue(type, out name))
|
||||||
|
return name;
|
||||||
|
XmlTypeAttribute att = type._GetAttribute<XmlTypeAttribute>();
|
||||||
|
if (att != null)
|
||||||
{
|
{
|
||||||
string name = ((XmlTypeAttribute)att[0]).TypeName;
|
name = att.TypeName;
|
||||||
if (!string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
return name;
|
name = type.Name;
|
||||||
}
|
}
|
||||||
return type.Name;
|
else
|
||||||
|
name = type.Name;
|
||||||
|
_CacheTypeName.Add(type, name);
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object _GetValue(XmlNode node, Type type)
|
private static object _GetValue(XmlNode node, Type type)
|
||||||
@@ -160,7 +214,7 @@ namespace VocaluxeLib.Xml
|
|||||||
return node.InnerText;
|
return node.InnerText;
|
||||||
if (type.IsPrimitive)
|
if (type.IsPrimitive)
|
||||||
return _GetPrimitiveValue(node, type);
|
return _GetPrimitiveValue(node, type);
|
||||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
|
if (type._IsList())
|
||||||
{
|
{
|
||||||
Type subType = type.GetGenericArguments()[0];
|
Type subType = type.GetGenericArguments()[0];
|
||||||
String subName = _GetTypeName(subType);
|
String subName = _GetTypeName(subType);
|
||||||
@@ -214,10 +268,9 @@ namespace VocaluxeLib.Xml
|
|||||||
_AddList(result, field, new List<object>());
|
_AddList(result, field, new List<object>());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
object[] defAtt = field.Info.GetCustomAttributes(typeof(DefaultValueAttribute), false);
|
if (!field.HasDefaultValue)
|
||||||
if (defAtt.Length == 0)
|
|
||||||
return field.IsNullable;
|
return field.IsNullable;
|
||||||
field.Info.SetValue(result, ((DefaultValueAttribute)defAtt[0]).Value);
|
field.Info.SetValue(result, field.DefaultValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user