using System; using System.Collections.Generic; using System.Xml.Linq; using JetBrains.Annotations; using UnityEngine; public static class HGXml { public delegate void Serializer(XElement element, T contents); public delegate bool Deserializer(XElement element, ref T contents); public class SerializationRules { public Serializer serializer; public Deserializer deserializer; public static SerializationRules defaultRules; static SerializationRules() { if (typeof(T).IsEnum) { RegisterEnum(); } } private static void RegisterEnum() { Type typeFromHandle = typeof(T); Dictionary nameToValue = new Dictionary(); string[] names = Enum.GetNames(typeFromHandle); for (int i = 0; i < names.Length; i++) { string text = names[i]; Enum.Parse(typeFromHandle, names[i]); nameToValue[text] = (T)Enum.Parse(typeFromHandle, text); } Dictionary valueToName = new Dictionary(); Array values = Enum.GetValues(typeFromHandle); for (int j = 0; j < values.Length; j++) { object value = values.GetValue(j); valueToName[(T)value] = Enum.GetName(typeFromHandle, value); } defaultRules = new SerializationRules { serializer = Serializer, deserializer = Deserializer }; bool Deserializer(XElement element, ref T contents) { if (nameToValue.TryGetValue(element.Value, out var value2)) { contents = value2; return true; } try { contents = (T)Enum.Parse(typeof(T), element.Value); return true; } catch (Exception) { } return false; } void Serializer(XElement element, T contents) { if (valueToName.TryGetValue(contents, out var value3)) { element.Value = value3; } else { element.Value = contents.ToString(); } } } } public static void Register(Serializer serializer, Deserializer deserializer) { SerializationRules.defaultRules = new SerializationRules { serializer = serializer, deserializer = deserializer }; } [NotNull] public static XElement ToXml(string name, T value) { return ToXml(name, value, SerializationRules.defaultRules); } [NotNull] public static XElement ToXml(string name, T value, SerializationRules rules) { XElement xElement = new XElement(name); rules.serializer(xElement, value); return xElement; } public static bool FromXml([NotNull] XElement element, ref T value) { return FromXml(element, ref value, SerializationRules.defaultRules); } public static bool FromXml([NotNull] XElement element, ref T value, SerializationRules rules) { if (rules == null) { Debug.LogFormat("Serialization rules not defined for type <{0}>", typeof(T).Name); return false; } return rules.deserializer(element, ref value); } public static bool FromXml([NotNull] XElement element, [NotNull] Action setter) { return FromXml(element, setter, SerializationRules.defaultRules); } public static bool FromXml([NotNull] XElement element, [NotNull] Action setter, [NotNull] SerializationRules rules) { T value = default(T); if (FromXml(element, ref value, rules)) { setter(value); return true; } return false; } static HGXml() { Register(delegate(XElement element, int contents) { element.Value = TextSerialization.ToStringInvariant(contents); }, delegate(XElement element, ref int contents) { if (TextSerialization.TryParseInvariant(element.Value, out int result8)) { contents = result8; return true; } return false; }); Register(delegate(XElement element, uint contents) { element.Value = TextSerialization.ToStringInvariant(contents); }, delegate(XElement element, ref uint contents) { if (TextSerialization.TryParseInvariant(element.Value, out uint result7)) { contents = result7; return true; } return false; }); Register(delegate(XElement element, ulong contents) { element.Value = TextSerialization.ToStringInvariant(contents); }, delegate(XElement element, ref ulong contents) { if (TextSerialization.TryParseInvariant(element.Value, out ulong result6)) { contents = result6; return true; } return false; }); Register(delegate(XElement element, bool contents) { element.Value = (contents ? "1" : "0"); }, delegate(XElement element, ref bool contents) { if (TextSerialization.TryParseInvariant(element.Value, out int result5)) { contents = result5 != 0; return true; } return false; }); Register(delegate(XElement element, float contents) { element.Value = TextSerialization.ToStringInvariant(contents); }, delegate(XElement element, ref float contents) { if (TextSerialization.TryParseInvariant(element.Value, out float result4)) { contents = result4; return true; } return false; }); Register(delegate(XElement element, double contents) { element.Value = TextSerialization.ToStringInvariant(contents); }, delegate(XElement element, ref double contents) { if (TextSerialization.TryParseInvariant(element.Value, out double result3)) { contents = result3; return true; } return false; }); Register(delegate(XElement element, string contents) { element.Value = contents; }, delegate(XElement element, ref string contents) { contents = element.Value; return true; }); Register(delegate(XElement element, Guid contents) { element.Value = contents.ToString(); }, delegate(XElement element, ref Guid contents) { if (Guid.TryParse(element.Value, out var result2)) { contents = result2; return true; } return false; }); Register(delegate(XElement element, DateTime contents) { element.Value = TextSerialization.ToStringInvariant(contents.ToBinary()); }, delegate(XElement element, ref DateTime contents) { if (TextSerialization.TryParseInvariant(element.Value, out long result)) { try { contents = DateTime.FromBinary(result); return true; } catch (ArgumentException) { } } return false; }); } public static void Deserialize(this XElement element, ref T dest) { FromXml(element, ref dest); } public static void Deserialize(this XElement element, ref T dest, SerializationRules rules) { FromXml(element, ref dest, rules); } public static void UsedOnlyForAOTCodeGeneration() { throw new InvalidOperationException("This method is used for AOT code generation only. Do not call it at runtime."); } }