|
| 1 | +using System; |
| 2 | +using System.Collections.Generic; |
| 3 | +using System.Linq; |
| 4 | +using System.Reflection; |
| 5 | +using System.Text; |
| 6 | +using System.Threading.Tasks; |
| 7 | +using System.Xml.Serialization; |
| 8 | + |
| 9 | +namespace DFe.Utils { |
| 10 | + |
| 11 | + public abstract class XmlOrderFreeSerializerFactory { |
| 12 | + // Referência https://stackoverflow.com/a/33508815 |
| 13 | + readonly static XmlAttributeOverrides overrides = new XmlAttributeOverrides(); |
| 14 | + readonly static object locker = new object(); |
| 15 | + readonly static Dictionary<Type, XmlSerializer> serializers = new Dictionary<Type, XmlSerializer>(); |
| 16 | + static HashSet<string> overridesAdded = new HashSet<string>(); |
| 17 | + |
| 18 | + static void AddOverrideAttributes(Type type, XmlAttributeOverrides overrides) { |
| 19 | + |
| 20 | + if (type == null || type == typeof(object) || type.IsPrimitive || type == typeof(string) || type == typeof(DateTime)) { |
| 21 | + return; |
| 22 | + } |
| 23 | + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { |
| 24 | + AddOverrideAttributes(type.GetGenericArguments()[0], overrides); |
| 25 | + return; |
| 26 | + } |
| 27 | + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) { |
| 28 | + AddOverrideAttributes(type.GetGenericArguments()[0], overrides); |
| 29 | + return; |
| 30 | + } |
| 31 | + |
| 32 | + var mask = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public; |
| 33 | + foreach (var member in type.GetProperties(mask).Cast<MemberInfo>().Union(type.GetFields(mask))) { |
| 34 | + var otTag = $"{type.Name}_{member.Name}"; |
| 35 | + if (overridesAdded.Contains(otTag)) { |
| 36 | + continue; |
| 37 | + } |
| 38 | + XmlAttributes overrideAttr = null; |
| 39 | + foreach (var attr in member.GetCustomAttributes<XmlElementAttribute>()) { |
| 40 | + overrideAttr = overrideAttr ?? new XmlAttributes(); |
| 41 | + var overrideElt = new XmlElementAttribute(attr.ElementName, attr.Type) { DataType = attr.DataType, ElementName = attr.ElementName, Form = attr.Form, Namespace = attr.Namespace, Type = attr.Type }; |
| 42 | + if(attr.IsNullable) { |
| 43 | + // Isso aqui deve ter uma logica personalizada no setter, colocar ali em cima causa erro |
| 44 | + overrideElt.IsNullable = true; |
| 45 | + } |
| 46 | + overrideAttr.XmlElements.Add(overrideElt); |
| 47 | + if(attr.Type != null) { |
| 48 | + AddOverrideAttributes(attr.Type, overrides); |
| 49 | + } |
| 50 | + } |
| 51 | + foreach (var attr in member.GetCustomAttributes<XmlArrayAttribute>()) { |
| 52 | + overrideAttr = overrideAttr ?? new XmlAttributes(); |
| 53 | + overrideAttr.XmlArray = new XmlArrayAttribute { ElementName = attr.ElementName, Form = attr.Form, IsNullable = attr.IsNullable, Namespace = attr.Namespace }; |
| 54 | + } |
| 55 | + foreach (var attr in member.GetCustomAttributes<XmlArrayItemAttribute>()) { |
| 56 | + overrideAttr = overrideAttr ?? new XmlAttributes(); |
| 57 | + overrideAttr.XmlArrayItems.Add(attr); |
| 58 | + } |
| 59 | + foreach (var attr in member.GetCustomAttributes<XmlAnyElementAttribute>()) { |
| 60 | + overrideAttr = overrideAttr ?? new XmlAttributes(); |
| 61 | + overrideAttr.XmlAnyElements.Add(new XmlAnyElementAttribute { Name = attr.Name, Namespace = attr.Namespace }); |
| 62 | + } |
| 63 | + if (overrideAttr != null) { |
| 64 | + overridesAdded.Add(otTag); |
| 65 | + overrides.Add(type, member.Name, overrideAttr); |
| 66 | + } |
| 67 | + var mType = (member is PropertyInfo pi ? pi.PropertyType : member is FieldInfo fi ? fi.FieldType : null); |
| 68 | + AddOverrideAttributes(mType, overrides); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + public static XmlSerializer GetSerializer(Type type) { |
| 73 | + if (type == null) |
| 74 | + throw new ArgumentNullException("type"); |
| 75 | + lock (locker) { |
| 76 | + XmlSerializer serializer; |
| 77 | + if (!serializers.TryGetValue(type, out serializer)) { |
| 78 | + AddOverrideAttributes(type, overrides); |
| 79 | + serializers[type] = serializer = new XmlSerializer(type, overrides); |
| 80 | + } |
| 81 | + return serializer; |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + } |
| 86 | + |
| 87 | + public static class TypeExtensions { |
| 88 | + public static IEnumerable<Type> BaseTypesAndSelf(this Type type) { |
| 89 | + while (type != null) { |
| 90 | + yield return type; |
| 91 | + type = type.BaseType; |
| 92 | + } |
| 93 | + } |
| 94 | + } |
| 95 | +} |
0 commit comments