public EXmlBase SerializeEXml(bool isChildTemplate) { Type type = GetType(); EXmlBase xmlData = new EXmlProperty { Value = type.Name + ".xml" }; if (!isChildTemplate) { xmlData = new EXmlData { Template = type.Name }; } var fields = type.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?) foreach (var field in fields) { NMSAttribute settings = field.GetCustomAttribute <NMSAttribute>(); if (settings == null) { settings = new NMSAttribute(); } if (settings.Ignore) { continue; } xmlData.Elements.Add(SerializeEXmlValue(field.FieldType, field, settings, field.GetValue(this))); } return(xmlData); }
public EXmlData SerializeEXml() { Type type = GetType(); EXmlData xmlData = new EXmlData { Template = type.Name }; var fields = type.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?) foreach (var field in fields) { if (field.Name.StartsWith("Padding")) { continue; } var fieldName = field.Name; var fieldType = field.FieldType.Name; switch (fieldType) { case "String": case "Single": case "Boolean": case "Int16": case "UInt16": case "Int32": case "UInt32": case "Int64": case "UInt64": var value = field.GetValue(this); var valueStr = value.ToString(); var valuesMethod = type.GetMethod(field.Name + "Values"); // if we have an "xxxValues()" method in the struct, use that to get the value name if (valuesMethod != null) { if (((int)value) == -1) { valueStr = ""; } else { string[] values = (string[])valuesMethod.Invoke(this, null); valueStr = values[(int)value]; } } xmlData.Elements.Add(new EXmlProperty { Name = fieldName, Value = valueStr }); break; case "Byte[]": byte[] bytes = (byte[])field.GetValue(this); string base64Value = bytes == null ? null : Convert.ToBase64String(bytes); xmlData.Elements.Add(new EXmlProperty { Name = fieldName, Value = base64Value }); break; case "List`1": EXmlProperty listProperty = new EXmlProperty { Name = fieldName }; IList templates = (IList)field.GetValue(this); foreach (var template in templates.Cast <NMSTemplate>()) { listProperty.Elements.Add(template.SerializeEXml()); } xmlData.Elements.Add(listProperty); break; case "NMSTemplate": if (field.GetValue(this) != null) { NMSTemplate template = (NMSTemplate)field.GetValue(this); EXmlData templateXmlData = template.SerializeEXml(); templateXmlData.Name = fieldName; xmlData.Elements.Add(templateXmlData); } break; default: if (field.FieldType.BaseType.Name == "NMSTemplate") { NMSTemplate template = (NMSTemplate)field.GetValue(this); EXmlData templateXmlData = template.SerializeEXml(); templateXmlData.Name = fieldName; xmlData.Elements.Add(templateXmlData); } break; } } return(xmlData); }
public static object DeserializeEXmlValue(NMSTemplate template, Type fieldType, FieldInfo field, EXmlProperty xmlProperty, Type templateType, NMSAttribute settings) { switch (fieldType.Name) { case "String": return(xmlProperty.Value); case "Single": return(float.Parse(xmlProperty.Value)); case "Boolean": return(bool.Parse(xmlProperty.Value)); case "Int16": return(short.Parse(xmlProperty.Value)); case "UInt16": return(ushort.Parse(xmlProperty.Value)); case "Int32": var valuesMethod = templateType.GetMethod(field.Name + "Values"); if (valuesMethod != null) { if (String.IsNullOrEmpty(xmlProperty.Value)) { return(-1); } else { string[] values = (string[])valuesMethod.Invoke(template, null); return(Array.FindIndex(values, v => v == xmlProperty.Value)); } } else if (settings?.EnumValue != null) { if (String.IsNullOrEmpty(xmlProperty.Value)) { return(-1); } else { return(Array.FindIndex(settings.EnumValue, v => v == xmlProperty.Value)); } } else { return(int.Parse(xmlProperty.Value)); } case "UInt32": return(uint.Parse(xmlProperty.Value)); case "Int64": return(long.Parse(xmlProperty.Value)); case "UInt64": return(ulong.Parse(xmlProperty.Value)); case "Byte[]": return(xmlProperty.Value == null ? null : Convert.FromBase64String(xmlProperty.Value)); case "List`1": Type elementType = fieldType.GetGenericArguments()[0]; Type listType = typeof(List <>).MakeGenericType(elementType); IList list = (IList)Activator.CreateInstance(listType); foreach (EXmlData innerXmlData in xmlProperty.Elements.OfType <EXmlData>()) // child templates { NMSTemplate element = DeserializeEXml(innerXmlData); list.Add(element); } foreach (EXmlProperty innerXmlData in xmlProperty.Elements.OfType <EXmlProperty>()) // primitive types { object element = DeserializeEXmlValue(template, elementType, field, innerXmlData, templateType, settings); list.Add(element); } return(list); default: if (field.FieldType.IsArray && field.FieldType.GetElementType().BaseType.Name == "NMSTemplate") { Array array = Array.CreateInstance(field.FieldType.GetElementType(), settings.Size); List <EXmlData> data = xmlProperty.Elements.OfType <EXmlData>().ToList(); for (int i = 0; i < data.Count; ++i) { NMSTemplate element = DeserializeEXml(data[i]); array.SetValue(element, i); } return(array); } else if (field.FieldType.IsArray) { Array array = Array.CreateInstance(field.FieldType.GetElementType(), settings.Size); List <EXmlProperty> data = xmlProperty.Elements.OfType <EXmlProperty>().ToList(); for (int i = 0; i < data.Count; ++i) { object element = DeserializeEXmlValue(template, field.FieldType.GetElementType(), field, data[i], templateType, settings); array.SetValue(element, i); } return(array); } else { return(fieldType.IsValueType ? Activator.CreateInstance(fieldType) : null); } } }
public EXmlBase SerializeEXmlValue(Type fieldType, FieldInfo field, NMSAttribute settings, object value) { string t = fieldType.Name; int i = 0; switch (fieldType.Name) { case "String": case "Single": case "Boolean": case "Int16": case "UInt16": case "Int32": case "UInt32": case "Int64": case "UInt64": var valueStr = value.ToString(); if (fieldType.Name == "Int32") { var valuesMethod = GetType().GetMethod(field.Name + "Values"); // if we have an "xxxValues()" method in the struct, use that to get the value name if (valuesMethod != null) { if (((int)value) == -1) { valueStr = ""; } else { string[] values = (string[])valuesMethod.Invoke(this, null); valueStr = values[(int)value]; } } else if (settings?.EnumValue != null) { if (((int)value) == -1) { valueStr = ""; } else { valueStr = settings.EnumValue[(int)value]; } } } return(new EXmlProperty { Name = field.Name, Value = valueStr }); case "Byte[]": byte[] bytes = (byte[])value; string base64Value = bytes == null ? null : Convert.ToBase64String(bytes); return(new EXmlProperty { Name = field.Name, Value = base64Value }); case "List`1": var listType = field.FieldType.GetGenericArguments()[0]; EXmlProperty listProperty = new EXmlProperty { Name = field.Name }; IList templates = (IList)value; i = 0; foreach (var template in templates) { EXmlBase data = SerializeEXmlValue(listType, field, settings, template); if (settings?.EnumValue != null) { data.Name = settings.EnumValue[i]; i++; } else { data.Name = null; } listProperty.Elements.Add(data); } return(listProperty); case "NMSTemplate": if (value != null) { NMSTemplate template = (NMSTemplate)value; EXmlData templateXmlData = template.SerializeEXml(); templateXmlData.Name = field.Name; return(templateXmlData); } return(null); default: if (fieldType.BaseType.Name == "NMSTemplate") { NMSTemplate template = (NMSTemplate)value; EXmlData templateXmlData = template.SerializeEXml(); templateXmlData.Name = field.Name; return(templateXmlData); } else if (fieldType.IsArray) { var arrayType = field.FieldType.GetElementType(); EXmlProperty arrayProperty = new EXmlProperty { Name = field.Name }; Array array = (Array)value; i = 0; foreach (var template in array) { EXmlBase data = SerializeEXmlValue(arrayType, field, settings, template); if (settings?.EnumValue != null) { data.Name = settings.EnumValue[i]; i++; } else { data.Name = null; } arrayProperty.Elements.Add(data); } return(arrayProperty); } else { throw new Exception(string.Format("Unable to encode {0} to EXml!", field)); } } }
public EXmlData SerializeEXml() { Type type = GetType(); EXmlData xmlData = new EXmlData { Template = type.Name }; var fields = type.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?) foreach (var field in fields) { NMSAttribute settings = field.GetCustomAttribute <NMSAttribute>(); if (settings == null) { settings = new NMSAttribute(); } if (settings.Ignore) { continue; } var fieldName = field.Name; var fieldType = field.FieldType.Name; switch (fieldType) { case "String": case "Single": case "Boolean": case "Int16": case "UInt16": case "Int32": case "UInt32": case "Int64": case "UInt64": var value = field.GetValue(this); var valueStr = value.ToString(); var valuesMethod = type.GetMethod(field.Name + "Values"); // if we have an "xxxValues()" method in the struct, use that to get the value name if (valuesMethod != null) { if (((int)value) == -1) { valueStr = ""; } else { string[] values = (string[])valuesMethod.Invoke(this, null); valueStr = values[(int)value]; } } else if (settings.EnumValue != null) { if (((int)value) == -1) { valueStr = ""; } else { valueStr = settings.EnumValue[(int)value]; } } xmlData.Elements.Add(new EXmlProperty { Name = fieldName, Value = valueStr }); break; case "Byte[]": byte[] bytes = (byte[])field.GetValue(this); string base64Value = bytes == null ? null : Convert.ToBase64String(bytes); xmlData.Elements.Add(new EXmlProperty { Name = fieldName, Value = base64Value }); break; case "List`1": EXmlProperty listProperty = new EXmlProperty { Name = fieldName }; IList templates = (IList)field.GetValue(this); foreach (var template in templates.Cast <NMSTemplate>()) { listProperty.Elements.Add(template.SerializeEXml()); } xmlData.Elements.Add(listProperty); break; case "NMSTemplate": if (field.GetValue(this) != null) { NMSTemplate template = (NMSTemplate)field.GetValue(this); EXmlData templateXmlData = template.SerializeEXml(); templateXmlData.Name = fieldName; xmlData.Elements.Add(templateXmlData); } break; default: if (field.FieldType.BaseType.Name == "NMSTemplate") { NMSTemplate template = (NMSTemplate)field.GetValue(this); EXmlData templateXmlData = template.SerializeEXml(); templateXmlData.Name = fieldName; xmlData.Elements.Add(templateXmlData); } else if (field.FieldType.IsArray && field.FieldType.GetElementType().BaseType.Name == "NMSTemplate") { var arrayType = field.FieldType.GetElementType(); EXmlProperty arrayProperty = new EXmlProperty { Name = fieldName }; Array array = (Array)field.GetValue(this); int i = 0; foreach (var template in array) { EXmlData data = ((NMSTemplate)template).SerializeEXml(); if (settings.EnumValue != null) { data.Name = settings.EnumValue[i]; i++; } arrayProperty.Elements.Add(data); } xmlData.Elements.Add(arrayProperty); } else { throw new Exception(string.Format("Unable to encode {0} to EXml!", field)); } break; } } return(xmlData); }
public static object DeserializeEXmlValue(NMSTemplate template, Type fieldType, FieldInfo field, EXmlProperty xmlProperty, Type templateType, NMSAttribute settings) { switch (fieldType.Name) { case "String": return(xmlProperty.Value); case "Single": return(float.Parse(xmlProperty.Value)); case "Boolean": return(bool.Parse(xmlProperty.Value)); case "Int16": return(short.Parse(xmlProperty.Value)); case "UInt16": return(ushort.Parse(xmlProperty.Value)); case "Int32": var valuesMethod = templateType.GetMethod(field.Name + "Values"); if (valuesMethod != null) { if (String.IsNullOrEmpty(xmlProperty.Value)) { return(-1); } else { string[] values = (string[])valuesMethod.Invoke(template, null); return(Array.FindIndex(values, v => v == xmlProperty.Value)); } } else if (settings?.EnumValue != null) { if (String.IsNullOrEmpty(xmlProperty.Value)) { return(-1); } else { return(Array.FindIndex(settings.EnumValue, v => v == xmlProperty.Value)); } } else { return(int.Parse(xmlProperty.Value)); } case "UInt32": return(uint.Parse(xmlProperty.Value)); case "Int64": return(long.Parse(xmlProperty.Value)); case "UInt64": return(ulong.Parse(xmlProperty.Value)); case "Byte[]": return(xmlProperty.Value == null ? null : Convert.FromBase64String(xmlProperty.Value)); case "List`1": Type elementType = fieldType.GetGenericArguments()[0]; Type listType = typeof(List <>).MakeGenericType(elementType); IList list = (IList)Activator.CreateInstance(listType); foreach (var innerXmlData in xmlProperty.Elements) // child templates { object element = null; if (innerXmlData.GetType() == typeof(EXmlData) || (innerXmlData.GetType() == typeof(EXmlProperty) && ((EXmlProperty)innerXmlData).Value.EndsWith(".xml"))) { element = DeserializeEXml(innerXmlData); // child template if <Data> tag or <Property> tag with value ending in .xml (todo: better way of finding <Property> child templates) } else if (innerXmlData.GetType() == typeof(EXmlProperty)) { element = DeserializeEXmlValue(template, elementType, field, (EXmlProperty)innerXmlData, templateType, settings); } if (element == null) { throw new Exception("element == null ??!"); } list.Add(element); } return(list); default: if (field.FieldType.IsArray && field.FieldType.GetElementType().BaseType.Name == "NMSTemplate") { Array array = Array.CreateInstance(field.FieldType.GetElementType(), settings.Size); var data = xmlProperty.Elements.OfType <EXmlProperty>().ToList(); if (data.Count != settings.Size) { // todo: add a comment in the XML to indicate arrays (+ their size), also need to do the same for showing valid enum values var error = $"{field.Name}: XML array size {data.Count} doesn't match expected array size {settings.Size}"; Console.WriteLine($"Error: {error}!"); Console.WriteLine("You might have added/removed an item from an array field"); Console.WriteLine("(arrays can't be shortened or extended as they're a fixed size set by the game)"); throw new Exception(error); } for (int i = 0; i < data.Count; ++i) { NMSTemplate element = DeserializeEXml(data[i]); array.SetValue(element, i); } return(array); } else if (field.FieldType.IsArray) { Array array = Array.CreateInstance(field.FieldType.GetElementType(), settings.Size); List <EXmlProperty> data = xmlProperty.Elements.OfType <EXmlProperty>().ToList(); for (int i = 0; i < data.Count; ++i) { object element = DeserializeEXmlValue(template, field.FieldType.GetElementType(), field, data[i], templateType, settings); array.SetValue(element, i); } return(array); } else { return(fieldType.IsValueType ? Activator.CreateInstance(fieldType) : null); } } }