/// <summary> /// Converts a member value to a string output, using MapConversion if available /// </summary> /// <param name="member">The class member whose value is to be converted</param> /// <param name="instance">The instance of the object with the given member</param> /// <returns></returns> private static string ConvertOut(object member, object instance) { try { MappingConversion mapConversion = (MappingConversion)GetCustomAttribute(member, typeof(MappingConversion)); if (mapConversion != null) { return(mapConversion.OutConversion(GetValue(member, instance))); } else { return(GetValue(member, instance)?.ToString()); } } catch (Exception e) { throw e; } }
/// <summary> /// Converts a string to a value output using the MapCOnversion if it is available /// </summary> /// <param name="member">The class member whose value is to be converted</param> /// <param name="value">The string value to convert to the desired out type</param> /// <returns></returns> private static object ConvertIn(object member, string value) { MappingConversion mapConversion = (MappingConversion)GetCustomAttribute(member, typeof(MappingConversion)); if (mapConversion != null) { return(mapConversion.InConversion(value)); } else { try { return(Convert.ChangeType(value, MemberType(member))); } catch { throw new MappableException($"Cannot automatically convert string '{value}' to type {MemberType(member)}. Consider using a value formatter."); } } }
/// <summary> /// Serializes a class into an XElement using the Mappable/Mapping attributes. /// Only public properties may be serialized /// </summary> /// <param name="serializable"></param> /// <returns></returns> public static XElement Serialize(object serializable, string rootElementName = null) { if (serializable == null) { return(null); } Type t = serializable.GetType(); Attribute[] attrs = Attribute.GetCustomAttributes(t); Mappable l = (Mappable)attrs.FirstOrDefault(a => a is Mappable); if (l == null) { return(null); } if (rootElementName != null) { l.Name = rootElementName; } // make the element XElement elm = new XElement(l.Name); var members = ((object[])t.GetFields()).Union(t.GetProperties()); // assign the attributes foreach (var member in members.Where(m => GetCustomAttribute(m, typeof(Mapping)) != null)) { Mapping trait = (Mapping)GetCustomAttribute(member, typeof(Mapping)); MappingConversion conversion = (MappingConversion)GetCustomAttribute(member, typeof(MappingConversion)); object value = ConvertOut(member, serializable); if (value == null && trait.Optional) { continue; } XAttribute attr = new XAttribute(trait.Name, value ?? ""); elm.Add(attr); } // assign values to simple lists var lists = members.Where(m => GetCustomAttribute(m, typeof(ListMapping)) != null); foreach (var listMember in lists) { ListMapping listMapping = (ListMapping)GetCustomAttribute(listMember, typeof(ListMapping)); IList children = GetValue(listMember, serializable) as IList; if (children == null) { throw new MappableException($"List '{listMapping.Name}' cannot be serialized: is not collection or is null"); } XElement listElm = new XElement(listMapping.Name); foreach (var child in children) { listElm.Add(Serialize(child)); } elm.Add(listElm); } // assign a value to the XElement var valueMapping = members.FirstOrDefault(m => GetCustomAttribute(m, typeof(ValueMapping)) != null); if (valueMapping != null) { string val = ConvertOut(valueMapping, serializable); if (val != null) { elm.Value = val; } } // assign the children foreach (var member in members.Where(m => GetCustomAttribute(m, typeof(ChildMapping)) != null)) { ChildMapping mapping = (ChildMapping)GetCustomAttribute(member, typeof(ChildMapping)); if (mapping.ChildType == null) { Mappable childMappable = (Mappable)MemberType(member).GetCustomAttribute(typeof(Mappable)); // maps only one value XElement childElm = Serialize(GetValue(member, serializable), rootElementName: childMappable.Name == null ? mapping.Name : null); if (childElm != null) { elm.Add(childElm); } } else { // mapped to many values IList children = GetValue(member, serializable) as IList; if (children == null) { return(null); } foreach (var child in children) { XElement childElm = Serialize(child); elm.Add(childElm); } } } // assign simple value children (non-Mappable children mapped to members of model) foreach (var member in members.Where(m => GetCustomAttribute(m, typeof(ValueChildMapping)) != null)) { ValueChildMapping mapping = (ValueChildMapping)GetCustomAttribute(member, typeof(ValueChildMapping)); XElement simpleChild = new XElement(mapping.Name); string val = ConvertOut(member, serializable); if (val != null) { simpleChild.Value = val; elm.Add(simpleChild); } } return(elm); }