diff options
author | majellin24 <majellin24@gmail.com> | 2018-10-31 12:43:46 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2018-10-31 12:43:46 +0300 |
commit | 92711632bf5b1cf2277f0169ad83daeedb721f25 (patch) | |
tree | fb11a6464514d17035bef890fe74a313fb76d228 /mcs/class/System.XML | |
parent | aa37f45a3d0fe94ed5ffcedb7324f5728bab7615 (diff) |
Modification to allow deserialization of derrived types (#11194)
* Modification to allow deserialization of derrived types
* white space correction
* second attempt
* third attempt
* fourth
* whitespace
* maybe fix null ref exception
* missed same condition in other method
* fixing condition
* hopefully correcting the test failure in AOT
* Modification to allow deserialization of derrived types
white space correction
second attempt
third attempt
fourth
whitespace
maybe fix null ref exception
missed same condition in other method
fixing condition
hopefully correcting the test failure in AOT
formatting
missed some formatting
* adding a test for PR #11194
* fixing a few exceptions
* adding ref
Diffstat (limited to 'mcs/class/System.XML')
4 files changed, 209 insertions, 11 deletions
diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs index d03dea1ff01..b1674117495 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs @@ -204,11 +204,9 @@ namespace System.Xml.Serialization { if (isNullable && ReadNull()) return null; - if (checkType) - { - System.Xml.XmlQualifiedName t = GetXsiType(); - if (t != null) - { + if (checkType) { + System.Xml.XmlQualifiedName t = GetXsiType(); + if (t != null) { XmlTypeMapping realMap = typeMap.GetRealElementMap (t.Name, t.Namespace); if (realMap == null) { if (typeMap.TypeData.Type == typeof(object)) @@ -221,7 +219,12 @@ namespace System.Xml.Serialization } else if (typeMap.TypeData.Type == typeof(object)) return ReadTypedPrimitive (AnyType); - } + else { + XmlTypeMapping realMap = typeMap.GetRealElementMap (Reader.LocalName, Reader.NamespaceURI); + if (realMap != null && realMap != typeMap) + return ReadObject(realMap, false, false); + } + } object ob = CreateInstance (typeMap.TypeData.Type, true); diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs index f70bd99464b..ff81f115b33 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs @@ -389,7 +389,7 @@ namespace System.Xml.Serialization return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey (name,ns, -1)]; } - public XmlTypeMapElementInfo GetElement(string name, string ns, int minimalOrder) + public XmlTypeMapElementInfo GetElement (string name, string ns, int minimalOrder) { if (_elements == null) return null; @@ -404,22 +404,38 @@ namespace System.Xml.Serialization selected = info; } } + else if (info.MappedType != null && info.MappedType.DerivedTypes.Count > 0) { + foreach (XmlTypeMapping derrivedInfo in info.MappedType.DerivedTypes) { + if (derrivedInfo.ElementName == name && derrivedInfo.Namespace == ns) { + if (info.ExplicitOrder < minimalOrder) + continue; + + if (selected == null || selected.ExplicitOrder > info.ExplicitOrder) { + selected = info; + } + } + } + } } return selected; } - public XmlTypeMapElementInfo GetElement(string name, string ns) + public XmlTypeMapElementInfo GetElement (string name, string ns) { if (_elements == null) return null; foreach (XmlTypeMapElementInfo info in _elements.Values) if (info.ElementName == name && info.Namespace == ns) return info; - + else if (info.MappedType != null && info.MappedType.DerivedTypes.Count > 0) { + foreach (XmlTypeMapping derrivedInfo in info.MappedType.DerivedTypes) + if (derrivedInfo.ElementName == name && derrivedInfo.Namespace == ns) + return info; + } return null; } - + public XmlTypeMapElementInfo GetElement (int index) { if (_elements == null) return null; diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs index 1393c354207..4695cfe64f0 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs @@ -1685,5 +1685,29 @@ namespace MonoTests.System.XmlSerialization Assert.AreEqual ("a", d.Extra[0]); Assert.AreEqual ("b", d.Extra[1]); } + + [Test] // PR #11194 + public void TestDerrivedClassProperty () + { + var data = "<layout width=\".25\" height =\".25\" x=\"0\" y=\"0\" id=\"portrait\" class=\"render\"><background color=\"white\"><div x=\".03\" y=\".05\" width=\".94\" height =\".9\" layout=\"proportional_rows\" paddingX=\".01\" paddingY=\".02\"><background color=\"black\"></background><background color=\"gray\" padding=\".1\"><label color=\"white\" font=\"emulogic.ttf\" fontSize=\"15\">Test UI</label></background><br brSize=\"1\" /><background class=\"back,Lab\" color=\"green\"><label class=\"Lab\" color=\"white\" font=\"emulogic.ttf\" fontSize=\"15\">GREEN</label></background><background color=\"red\"><label class=\"Lab\" color=\"white\" font=\"emulogic.ttf\" fontSize=\"15\">RED</label></background><background color=\"blue\"><label class=\"Lab\" color=\"white\" font=\"emulogic.ttf\" fontSize=\"15\">TLUE</label></background><background color=\"blue\"><label class=\"Lab\" color=\"white\" font=\"emulogic.ttf\" fontSize=\"15\">BLUE</label></background></div></background></layout>"; + + XmlAttributeOverrides overrides = PR11194.GenerateLayoutOverrides<PR11194ChildLo>(); + + var result = Deserialize(typeof(PR11194ChildLo), data, overrides) as PR11194ChildLo; + + PR11194Parent2 child; + Assert.IsNotNull(result, "#11194_1"); + Assert.AreEqual(1, result.children.Count, "#11194_2"); + child = result.children[0] as PR11194Parent2; + Assert.IsNotNull(child, "#11194_3"); + Assert.AreEqual(1, child.children.Count, "#11194_4"); + child = child.children[0] as PR11194Parent2; + Assert.IsNotNull(child, "#11194_5"); + Assert.AreEqual(7, child.children.Count, "#11194_6"); + child = child.children[1] as PR11194Parent2; + Assert.IsNotNull(child, "#11194_7"); + Assert.AreEqual(1, child.children.Count, "#11194_8"); + Assert.AreEqual("PR11194ChildL", child.children[0].GetType().Name, "#11194_9"); + } } } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs index 4adcc11b20d..167d991e092 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs @@ -12,6 +12,8 @@ // using System; +using System.Linq; +using System.Reflection; using System.Collections; using System.Collections.Generic; using System.ComponentModel; @@ -1203,6 +1205,159 @@ namespace MonoTests.System.Xml.TestClasses public ClassWithDefaultTextNotNull () { Value = DefaultValue; } - } + } + + + #region PR_11194 + + #region PR_11194_GenerateOverrides + public static class PR11194 + { + public static XmlAttributeOverrides GenerateLayoutOverrides<T>() + { + Type tType = typeof(T); + + TypeInfo tTypeInfo = tType.GetTypeInfo(); + + IEnumerable<PropertyInfo> props = tType.GetRuntimeProperties(); + + XmlAttributeOverrides overrides = new XmlAttributeOverrides(); + + foreach (PropertyInfo prop in props) { + XmlDerrivedAttribute attr = prop.GetCustomAttribute<XmlDerrivedAttribute>(); + + if (attr == null) { + continue; + } + + Type dType = prop.DeclaringType; + + Type pType = prop.PropertyType; + TypeInfo pTypeInfo = pType.GetTypeInfo(); + + Type enumType = typeof(IEnumerable<>); + + if (pTypeInfo.IsGenericType + && pTypeInfo.ImplementedInterfaces.Any(t => + (t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == enumType))) { + pType = pType.GenericTypeArguments[0]; + } + + XmlAttributes overrideAttributes = GenerateOverrideAttributes(dType, pType, attr); + + overrides.Add(dType, prop.Name, overrideAttributes); + } + + return overrides; + } + + private static XmlAttributes GenerateOverrideAttributes (Type declaringType, Type propertyType, XmlDerrivedAttribute attr) + { + XmlAttributes xAttrs = new XmlAttributes(); + + Assembly a = declaringType.GetTypeInfo().Assembly; + TypeInfo interfaceType = propertyType.GetTypeInfo(); + IEnumerable<Type> types = a.ExportedTypes.Where(t => interfaceType.IsAssignableFrom(t.GetTypeInfo()) && !t.GetTypeInfo().IsAbstract); + + foreach (Type t in types) { + string name = NameBySourceType(t, attr.SrcType);// t.GetTypeInfo().GetCustomAttribute<XmlTypeAttribute>().TypeName; + XmlElementAttribute xAttr = new XmlElementAttribute(); + xAttr.ElementName = name; + xAttr.Type = t; + xAttrs.XmlElements.Add(xAttr); + } + + return xAttrs; + } + + private static string NameBySourceType (Type derrivedType, XmlDerrivedSourceType srcType) + { + string name = null; + switch (srcType) + { + case XmlDerrivedSourceType.ByXmlType: + name = derrivedType.GetTypeInfo().GetCustomAttribute<XmlTypeAttribute>().TypeName; + break; + } + return name; + } + } + #endregion + + #region helperAttribute + public enum XmlDerrivedSourceType + { + ByXmlType + } + + public class XmlDerrivedAttribute : Attribute + { + public XmlDerrivedSourceType SrcType { get; set; } + + public XmlDerrivedAttribute(XmlDerrivedSourceType srcType) + { + SrcType = srcType; + } + } + #endregion + + public abstract class PR11194Parent + { + [XmlIgnore] + public PR11194Parent Parent { get; set; } + } + + public abstract class PR11194Parent2 : PR11194Parent + { + [XmlAttribute] + public float width { get; set; } + [XmlAttribute] + public float height { get; set; } + [XmlAttribute] + public float x { get; set; } + [XmlAttribute] + public float y { get; set; } + [XmlAttribute] + public string id { get; set; } + [XmlElement] + [XmlDerrived(XmlDerrivedSourceType.ByXmlType)] + public List<PR11194Parent> children { get; set; } + } + + [XmlType("background")] + public class PR11194ChildB : PR11194Parent2 + { + [XmlAttribute] + public string image { get; set; } + } + + [XmlType("br")] + public class PR11194ChildBr : PR11194Parent + { + [XmlAttribute("brSize")] + public int breaks { get; set; } + } + + [XmlType("div")] + public class PR11194ChildD : PR11194ChildLo + { + } + + [XmlType("label")] + public class PR11194ChildL : PR11194Parent2 + { + [XmlAttribute] + public string font { get; set; } + [XmlAttribute] + public int fontSize { get; set; } + [XmlText] + public string Text { get; set; } + } + + [XmlType("layout")] + public class PR11194ChildLo : PR11194Parent2 + { + } + #endregion } |