Serialize properties

This commit is contained in:
Flamefire committed 2014-10-27 19:44:23 +01:00
1 parent 1698c1b027
commit af88bb2161
3 files changed
+163 -87

No files matched your search

+123 -78
View File
@@ -40,9 +40,15 @@ namespace VocaluxeLib.Xml
public struct SFieldInfo
{
private readonly FieldInfo _Field;
private readonly PropertyInfo _Property;
public Type Type
{
get { return _Field != null ? _Field.FieldType : _Property.PropertyType; }
}
public string Name;
public string AltName;
public FieldInfo Info;
public object DefaultValue;
public bool HasDefaultValue;
public bool IsAttribute;
@@ -54,6 +60,31 @@ namespace VocaluxeLib.Xml
public XmlRangedAttribute Ranged;
public Type SubType;
public string ArrayItemName;
public SFieldInfo(FieldInfo field)
: this()
{
_Field = field;
}
public SFieldInfo(PropertyInfo property)
: this()
{
_Property = property;
}
public void SetValue(object o, object value)
{
if (_Field != null)
_Field.SetValue(o, value);
else
_Property.SetValue(o, value, new object[] {});
}
public object GetValue(object o)
{
return (_Field != null) ?_Field.GetValue(o) :_Property.GetValue(o, new object[] {});
}
}
public static class CTypeExtensions
@@ -61,6 +92,86 @@ namespace VocaluxeLib.Xml
private static readonly Dictionary<Type, List<SFieldInfo>> _CacheFields = new Dictionary<Type, List<SFieldInfo>>();
private static readonly Dictionary<Type, String> _CacheTypeName = new Dictionary<Type, string>();
private static void _FillInfo(ref SFieldInfo info, MemberInfo field)
{
XmlAttributeAttribute attribute = field.GetAttribute<XmlAttributeAttribute>();
if (attribute != null)
{
info.IsAttribute = true;
info.Name = attribute.AttributeName;
}
else
{
XmlElementAttribute element = field.GetAttribute<XmlElementAttribute>();
if (element != null)
info.Name = element.ElementName;
else
{
XmlArrayAttribute array = field.GetAttribute<XmlArrayAttribute>();
if (array != null)
{
Debug.Assert(info.Type.IsList() || info.Type.IsArray, "Only lists and arrays can have the array attribute");
Debug.Assert(!info.IsAttribute, "Lists cannot be attributes");
info.Name = array.ElementName;
info.IsList = true;
}
}
}
if (string.IsNullOrEmpty(info.Name))
info.Name = field.Name;
XmlAltNameAttribute altName = field.GetAttribute<XmlAltNameAttribute>();
if (altName != null)
info.AltName = altName.AltName;
if (info.Type.IsGenericType)
info.SubType = info.Type.GetGenericArguments().Last();
if (info.Type.IsArray)
info.SubType = info.Type.GetElementType();
if (info.Type.IsList() || info.Type.IsArray)
{
if (!info.IsList)
{
Debug.Assert(!field.HasAttribute<XmlArrayAttribute>(), "A field cannot have an XmlElement- and XmlArray-Attribute");
info.IsEmbeddedList = true;
}
else
{
XmlArrayItemAttribute arrayItem = field.GetAttribute<XmlArrayItemAttribute>();
if (arrayItem != null && !string.IsNullOrEmpty(arrayItem.ElementName))
info.ArrayItemName = arrayItem.ElementName;
}
}
else if (info.Type.IsNullable())
info.IsNullable = true;
else if (info.Type.IsDictionary())
{
Debug.Assert(info.Type.GetGenericArguments()[0] == typeof(string), "Keys of dictionaries must be strings");
info.IsDictionary = true;
}
if (field.HasAttribute<XmlNormalizedAttribute>())
{
Debug.Assert(info.Type == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized");
info.IsNormalized = true;
}
info.Ranged = field.GetAttribute<XmlRangedAttribute>();
Debug.Assert(info.Ranged == null || info.Type == typeof(int) || info.Type == typeof(float) || info.Type == typeof(double),
"Only ints,floats and double can be ranged");
DefaultValueAttribute defAttr = field.GetAttribute<DefaultValueAttribute>();
if (defAttr != null)
{
Debug.Assert(!info.Type.IsList(), "Lists cannot have a default value");
info.HasDefaultValue = true;
info.DefaultValue = defAttr.Value;
}
else if (info.IsNullable)
{
info.HasDefaultValue = true;
info.DefaultValue = null;
}
}
public static IEnumerable<SFieldInfo> GetFieldInfos(this Type type)
{
List<SFieldInfo> result;
@@ -72,83 +183,17 @@ namespace VocaluxeLib.Xml
{
if (field.HasAttribute<XmlIgnoreAttribute>())
continue;
XmlAttributeAttribute attribute = field.GetAttribute<XmlAttributeAttribute>();
SFieldInfo info = new SFieldInfo {Info = field};
if (attribute != null)
{
info.IsAttribute = true;
info.Name = attribute.AttributeName;
}
else
{
XmlElementAttribute element = field.GetAttribute<XmlElementAttribute>();
if (element != null)
info.Name = element.ElementName;
else
{
XmlArrayAttribute array = field.GetAttribute<XmlArrayAttribute>();
if (array != null)
{
Debug.Assert(field.FieldType.IsList() || field.FieldType.IsArray, "Only lists and arrays can have the array attribute");
Debug.Assert(!info.IsAttribute, "Lists cannot be attributes");
info.Name = array.ElementName;
info.IsList = true;
}
}
}
if (string.IsNullOrEmpty(info.Name))
info.Name = field.Name;
XmlAltNameAttribute altName = field.GetAttribute<XmlAltNameAttribute>();
if (altName != null)
info.AltName = altName.AltName;
if (field.FieldType.IsGenericType)
info.SubType = field.FieldType.GetGenericArguments().Last();
if (field.FieldType.IsArray)
info.SubType = field.FieldType.GetElementType();
if (field.FieldType.IsList() || field.FieldType.IsArray)
{
if (!info.IsList)
{
Debug.Assert(!field.HasAttribute<XmlArrayAttribute>(), "A field cannot have an XmlElement- and XmlArray-Attribute");
info.IsEmbeddedList = true;
}
else
{
XmlArrayItemAttribute arrayItem = field.GetAttribute<XmlArrayItemAttribute>();
if (arrayItem != null && !string.IsNullOrEmpty(arrayItem.ElementName))
info.ArrayItemName = arrayItem.ElementName;
}
}
else if (field.FieldType.IsNullable())
info.IsNullable = true;
else if (field.FieldType.IsDictionary())
{
Debug.Assert(field.FieldType.GetGenericArguments()[0] == typeof(string), "Keys of dictionaries must be strings");
info.IsDictionary = true;
}
if (field.HasAttribute<XmlNormalizedAttribute>())
{
Debug.Assert(field.FieldType == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized");
info.IsNormalized = true;
}
info.Ranged = field.GetAttribute<XmlRangedAttribute>();
Debug.Assert(info.Ranged == null || field.FieldType == typeof(int) || field.FieldType == typeof(float) || field.FieldType == typeof(double),
"Only ints,floats and double can be ranged");
DefaultValueAttribute defAttr = field.GetAttribute<DefaultValueAttribute>();
if (defAttr != null)
{
Debug.Assert(!field.FieldType.IsList(), "Lists cannot have a default value");
info.HasDefaultValue = true;
info.DefaultValue = defAttr.Value;
}
else if (info.IsNullable)
{
info.HasDefaultValue = true;
info.DefaultValue = null;
}
SFieldInfo info = new SFieldInfo(field);
_FillInfo(ref info, field);
result.Add(info);
}
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo property in properties)
{
if (property.HasAttribute<XmlIgnoreAttribute>())
continue;
SFieldInfo info = new SFieldInfo(property);
_FillInfo(ref info, property);
result.Add(info);
}
_CacheFields.Add(type, result);