From ef23f4f0cc29c2ace5a209d2e868024780ffeee8 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Fri, 20 Apr 2007 11:13:46 +0000 Subject: [PATCH] 2007-04-20 Atsushi Enomoto * XmlTypeMapping.cs, ReflectionHelper.cs, XmlSerializationReaderInterpreter.cs, SerializationCodeGenerator.cs: support instantiation by private constructor. * XmlSerializerTests.cs : Added test for serializing private-constructor-only class. svn path=/trunk/mcs/; revision=76003 --- .../System.Xml.Serialization/ChangeLog | 6 ++++++ .../ReflectionHelper.cs | 8 +++++++- .../SerializationCodeGenerator.cs | 12 ++++++------ .../XmlSerializationReaderInterpreter.cs | 12 ++++++------ .../XmlTypeMapping.cs | 2 +- .../Test/System.Xml.Serialization/ChangeLog | 5 +++++ .../XmlSerializerTests.cs | 19 +++++++++++++++++++ 7 files changed, 50 insertions(+), 14 deletions(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/ChangeLog b/mcs/class/System.XML/System.Xml.Serialization/ChangeLog index 04e65d0b850..5f28bb82201 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/ChangeLog +++ b/mcs/class/System.XML/System.Xml.Serialization/ChangeLog @@ -1,3 +1,9 @@ +2007-04-20 Atsushi Enomoto + + * XmlTypeMapping.cs, ReflectionHelper.cs, + XmlSerializationReaderInterpreter.cs, SerializationCodeGenerator.cs: + support instantiation by private constructor. + 2007-04-19 Konstantin Triger * XmlSchemaExporter.cs: do not export twice simple types. diff --git a/mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs b/mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs index 0461aa75d9c..1b5ece9a8e8 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs @@ -70,12 +70,18 @@ namespace System.Xml.Serialization { return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message); } - + + static readonly ParameterModifier [] empty_modifiers = new ParameterModifier [0]; + public static void CheckSerializableType (Type type, bool allowPrivateConstructors) { if (type.IsArray) return; +#if NET_2_0 + if (!allowPrivateConstructors && type.GetConstructor (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, empty_modifiers) == null && !type.IsAbstract && !type.IsValueType) +#else if (!allowPrivateConstructors && type.GetConstructor (Type.EmptyTypes) == null && !type.IsAbstract && !type.IsValueType) +#endif throw new InvalidOperationException (type.FullName + " cannot be serialized because it does not have a default public constructor"); if (type.IsInterface && !TypeTranslator.GetTypeData (type).IsListType) diff --git a/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs b/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs index 64a09cf94a6..a1db7ac6f79 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs @@ -1440,7 +1440,7 @@ namespace System.Xml.Serialization XmlTypeMapMember mem = (XmlTypeMapMember) members [n]; if (!mem.IsReturnValue && mem.TypeData.IsValueType) GenerateSetMemberValueFromAttr (mem, "parameters", - "new " + mem.TypeData.FullTypeName + "()", true); + String.Format ("({0}) Activator.CreateInstance(typeof({0}), true)", mem.TypeData.FullTypeName), true); } WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.ReadState == ReadState.Interactive)"); @@ -1540,7 +1540,7 @@ namespace System.Xml.Serialization } else { - WriteLine (typeMap.TypeData.CSharpFullName + " ob = new " + typeMap.TypeData.CSharpFullName + " ();"); + WriteLine (typeMap.TypeData.CSharpFullName + String.Format (" ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName)); if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) { WriteLine ("return ob;"); @@ -1580,7 +1580,7 @@ namespace System.Xml.Serialization } WriteLine (""); - WriteLine ("ob = new " + typeMap.TypeData.CSharpFullName + " ();"); + WriteLine (String.Format ("ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName)); } WriteLine (""); @@ -2130,7 +2130,7 @@ namespace System.Xml.Serialization return GetReadObjectCall (elem.MappedType, GetLiteral(elem.IsNullable), "true"); case SchemaTypes.XmlSerializable: - return GetCast (elem.TypeData, "ReadSerializable (new " + elem.TypeData.CSharpFullName + " ())"); + return GetCast (elem.TypeData, String.Format ("ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true))", elem.TypeData.CSharpFullName)); default: throw new NotSupportedException ("Invalid value type"); @@ -2299,7 +2299,7 @@ namespace System.Xml.Serialization { WriteLine ("if (((object)" + list + ") == null)"); if (canCreateInstance) - WriteLine ("\t" + list + " = new " + listType.CSharpFullName + "();"); + WriteLine ("\t" + list + String.Format (" = ({0}) Activator.CreateInstance(typeof({0}), true);", listType.CSharpFullName)); else WriteLine ("\tthrow CreateReadOnlyCollectionException (" + GetLiteral (listType.CSharpFullName) + ");"); @@ -2420,7 +2420,7 @@ namespace System.Xml.Serialization WriteLine ("if (Reader.NodeType == XmlNodeType.Element)"); WriteLineInd ("{"); WriteLine ("if (Reader.LocalName == " + GetLiteral (typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")"); - WriteLine ("\treturn ReadSerializable (new " + typeMap.TypeData.CSharpFullName + "());"); + WriteLine (String.Format ("\treturn ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true));", typeMap.TypeData.CSharpFullName)); WriteLine ("else"); WriteLine ("\tthrow CreateUnknownNodeException ();"); WriteLineUni ("}"); diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs index 367f1e79581..f2b8e212d1d 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs @@ -223,7 +223,7 @@ namespace System.Xml.Serialization return ReadTypedPrimitive (AnyType); } - object ob = Activator.CreateInstance (typeMap.TypeData.Type); + object ob = Activator.CreateInstance (typeMap.TypeData.Type, true); Reader.MoveToElement(); bool isEmpty = Reader.IsEmptyElement; @@ -623,7 +623,7 @@ namespace System.Xml.Serialization return ReadObject (elem.MappedType, elem.IsNullable, true); case SchemaTypes.XmlSerializable: - object ob = Activator.CreateInstance (elem.TypeData.Type); + object ob = Activator.CreateInstance (elem.TypeData.Type, true); return ReadSerializable ((IXmlSerializable)ob); default: @@ -734,7 +734,7 @@ namespace System.Xml.Serialization else // Must be IEnumerable { if (list == null) { - if (canCreateInstance) list = Activator.CreateInstance (type); + if (canCreateInstance) list = Activator.CreateInstance (type, true); else throw CreateReadOnlyCollectionException (type.FullName); } @@ -753,7 +753,7 @@ namespace System.Xml.Serialization if (listType.IsArray) return EnsureArrayIndex (null, 0, listType.GetElementType()); else - return Activator.CreateInstance (listType); + return Activator.CreateInstance (listType, true); } object InitializeList (TypeData listType) @@ -761,7 +761,7 @@ namespace System.Xml.Serialization if (listType.Type.IsArray) return null; else - return Activator.CreateInstance (listType.Type); + return Activator.CreateInstance (listType.Type, true); } void FillList (object list, object items) @@ -825,7 +825,7 @@ namespace System.Xml.Serialization { if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace) { - object ob = Activator.CreateInstance (typeMap.TypeData.Type); + object ob = Activator.CreateInstance (typeMap.TypeData.Type, true); return ReadSerializable ((IXmlSerializable)ob); } else diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs index d0e35adfc48..8554787fe85 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs @@ -193,7 +193,7 @@ namespace System.Xml.Serialization internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace) : base(elementName, ns, typeData, xmlType, xmlTypeNamespace) { - IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type); + IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type, true); _schema = serializable.GetSchema(); if (_schema != null) { diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/ChangeLog b/mcs/class/System.XML/Test/System.Xml.Serialization/ChangeLog index b5dab02b0ea..6da11a455b6 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/ChangeLog +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/ChangeLog @@ -1,3 +1,8 @@ +2007-04-20 Atsushi Enomoto + + * XmlSerializerTests.cs : + Added test for serializing private-constructor-only class. + 2007-02-20 Atsushi Enomoto * XmlSerializationReaderTests.cs : test non-empty element as well. diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index b5836e69906..4be34bc3ac2 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -2585,6 +2585,16 @@ namespace MonoTests.System.XmlSerialization stream.Position = 0; foo = (Bug80759) serializer.Deserialize (stream); } + + [Test] + public void SupportPrivateCtorOnly () + { + XmlSerializer xs = + new XmlSerializer (typeof (PrivateCtorOnly)); + StringWriter sw = new StringWriter (); + xs.Serialize (sw, PrivateCtorOnly.Instance); + xs.Deserialize (new StringReader (sw.ToString ())); + } #endif #endregion //GenericsSeralizationTests @@ -2646,6 +2656,15 @@ namespace MonoTests.System.XmlSerialization public byte[] Data = new byte[] { 1, 2, 3 }; } + [XmlRoot ("PrivateCtorOnly")] + public class PrivateCtorOnly + { + public static PrivateCtorOnly Instance = new PrivateCtorOnly (); + private PrivateCtorOnly () + { + } + } + public class CDataTextNodesType { public CDataTextNodesInternal foo; -- 2.25.1