From 4a5f7c742c650c001a25cc5c60bcb852f155cca5 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Thu, 20 Jan 2011 16:16:56 +0900 Subject: [PATCH] Contract-based type must ensure that the base type is also contract-based. Fixed bug #661987 on WCF side. --- .../DataContractSerializer.cs | 2 +- .../KnownTypeCollection.cs | 6 ++++ .../SerializationMap.cs | 18 +++++++++++ .../XmlObjectSerializerTest.cs | 32 +++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/DataContractSerializer.cs b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/DataContractSerializer.cs index d44a4162a06..3cfe9d55156 100755 --- a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/DataContractSerializer.cs +++ b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/DataContractSerializer.cs @@ -386,7 +386,7 @@ namespace System.Runtime.Serialization } #endif - [MonoTODO ("support arrays; support Serializable; support SharedType; use DataContractSurrogate")] + [MonoTODO ("use DataContractSurrogate")] /* when writeContentOnly is true, then the input XmlWriter must be at element state. This is to write possible diff --git a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs index 0b742de43bf..66fb3c52abf 100755 --- a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs +++ b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs @@ -792,6 +792,12 @@ namespace System.Runtime.Serialization contracts.Add (ret); ret.Initialize (); + if (type.BaseType != typeof (object)) { + TryRegister (type.BaseType); + if (!FindUserMap (type.BaseType).IsContractAllowedType) + throw new InvalidDataContractException (String.Format ("To be serializable by data contract, type '{0}' cannot inherit from non-contract and non-Serializable type '{1}'", type, type.BaseType)); + } + object [] attrs = type.GetCustomAttributes (typeof (KnownTypeAttribute), true); for (int i = 0; i < attrs.Length; i++) { KnownTypeAttribute kt = (KnownTypeAttribute) attrs [i]; diff --git a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs index 5f1f2ac8645..58f92373e8a 100644 --- a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs +++ b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs @@ -124,6 +124,8 @@ namespace System.Runtime.Serialization public QName XmlName { get; set; } + public abstract bool IsContractAllowedType { get; } + protected void HandleId (XmlReader reader, XmlFormatterDeserializer deserializer, object instance) { HandleId (reader.GetAttribute ("Id", KnownTypeCollection.MSSimpleNamespace), deserializer, instance); @@ -381,6 +383,8 @@ namespace System.Runtime.Serialization internal partial class XmlSerializableMap : SerializationMap { + public override bool IsContractAllowedType { get { return true; } } + public XmlSerializableMap (Type type, QName qname, KnownTypeCollection knownTypes) : base (type, qname, knownTypes) { @@ -419,6 +423,8 @@ namespace System.Runtime.Serialization { } + public override bool IsContractAllowedType { get { return true; } } + internal void Initialize () { Type type = RuntimeType; @@ -483,6 +489,8 @@ namespace System.Runtime.Serialization { } + public override bool IsContractAllowedType { get { return false; } } + internal void Initialize () { Members.AddRange (GetDefaultMembers ()); @@ -529,6 +537,8 @@ namespace System.Runtime.Serialization internal override string CurrentNamespace { get { return XmlName.Namespace; } } + + public override bool IsContractAllowedType { get { return true; } } } internal interface ICollectionTypeMap @@ -574,6 +584,8 @@ namespace System.Runtime.Serialization return null; } + public override bool IsContractAllowedType { get { return false; } } + public override bool OutputXsiType { get { return false; } } @@ -717,6 +729,8 @@ namespace System.Runtime.Serialization get { return a != null && !String.IsNullOrEmpty (a.Namespace) ? a.Namespace : KnownTypeCollection.MSArraysNamespace; } } + public override bool IsContractAllowedType { get { return a != null; } } + public Type KeyType { get { return key_type; } } public Type ValueType { get { return value_type; } } @@ -872,6 +886,8 @@ namespace System.Runtime.Serialization { } + public override bool IsContractAllowedType { get { return true; } } + public void Initialize () { Members = GetMembers (RuntimeType, XmlName, false); @@ -944,6 +960,8 @@ namespace System.Runtime.Serialization } } + public override bool IsContractAllowedType { get { return false; } } + private EnumMemberAttribute GetEnumMemberAttribute ( MemberInfo mi) { diff --git a/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs b/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs index 30e878330c8..4a194d8daed 100755 --- a/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs +++ b/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs @@ -1499,6 +1499,19 @@ namespace MonoTests.System.Runtime.Serialization var ds = (DataSet) x.ReadObject (r); } + + [Test] + [ExpectedException (typeof (InvalidDataContractException))] // BaseConstraintType1 is neither DataContract nor Serializable. + public void BaseConstraint1 () + { + new DataContractSerializer (typeof (BaseConstraintType3)).WriteObject (XmlWriter.Create (TextWriter.Null), new BaseConstraintType3 ()); + } + + [Test] + public void BaseConstraint2 () + { + new DataContractSerializer (typeof (BaseConstraintType4)).WriteObject (XmlWriter.Create (TextWriter.Null), new BaseConstraintType4 ()); + } } [DataContract] @@ -1800,6 +1813,25 @@ namespace MonoTests.System.Runtime.Serialization [DataMember] public string X = "x"; } + + class BaseConstraintType1 // non-serializable + { + } + + [Serializable] + class BaseConstraintType2 + { + } + + [DataContract] + class BaseConstraintType3 : BaseConstraintType1 + { + } + + [DataContract] + class BaseConstraintType4 : BaseConstraintType2 + { + } } [DataContract] -- 2.25.1