Explorar el Código

* ReflectionHelper.cs, SoapReflectionImporter.cs, XmlReflectionImporter.cs:
In CheckSerializableType, add the option of ignoring types with private
constructors. Some kind of lists can be deserialized
even if the constructor is private. See bug #61464.
* SerializationCodeGenerator.cs, XmlSerializationReaderInterpreter.cs:
Before creating a list, check that it has a public constructor.
* TypeData.cs: Added HasPublicConstructor property.

svn path=/trunk/mcs/; revision=33230

Lluis Sanchez hace 21 años
padre
commit
d996305ce2

+ 10 - 0
mcs/class/System.XML/System.Xml.Serialization/ChangeLog

@@ -1,3 +1,13 @@
+2004-09-02  Lluis Sanchez Gual  <[email protected]>
+
+	* ReflectionHelper.cs, SoapReflectionImporter.cs, XmlReflectionImporter.cs: 
+	  In CheckSerializableType, add the option of ignoring types with private
+	  constructors. Some kind of lists can be deserialized
+	  even if the constructor is private. See bug #61464.
+	* SerializationCodeGenerator.cs, XmlSerializationReaderInterpreter.cs:
+	  Before creating a list, check that it has a public constructor.
+	* TypeData.cs: Added HasPublicConstructor property.
+
 2004-09-01  Lluis Sanchez Gual  <[email protected]>
 2004-09-01  Lluis Sanchez Gual  <[email protected]>
 
 
 	* SerializationCodeGenerator.cs: Generate correct "HasValue" check for
 	* SerializationCodeGenerator.cs: Generate correct "HasValue" check for

+ 2 - 2
mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs

@@ -71,11 +71,11 @@ namespace System.Xml.Serialization
 			return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message);
 			return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message);
 		}
 		}
 		
 		
-		public static void CheckSerializableType (Type type)
+		public static void CheckSerializableType (Type type, bool allowPrivateConstructors)
 		{
 		{
 			if (type.IsArray) return;
 			if (type.IsArray) return;
 			
 			
-			if (type.GetConstructor (Type.EmptyTypes) == null && !type.IsAbstract && !type.IsValueType)
+			if (!allowPrivateConstructors && type.GetConstructor (Type.EmptyTypes) == null && !type.IsAbstract && !type.IsValueType)
 				throw new InvalidOperationException (type.FullName + " cannot be serialized because it does not have a default public constructor");
 				throw new InvalidOperationException (type.FullName + " cannot be serialized because it does not have a default public constructor");
 				
 				
 			if (type.IsInterface)
 			if (type.IsInterface)

+ 24 - 14
mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs

@@ -1622,7 +1622,7 @@ namespace System.Xml.Serialization
 						if (!MemberHasReadReplaceHook (xmlMapType, mem)) {
 						if (!MemberHasReadReplaceHook (xmlMapType, mem)) {
 							flatLists[n] = GetObTempVar ();
 							flatLists[n] = GetObTempVar ();
 							string rval = "null";
 							string rval = "null";
-							if (IsReadOnly (typeMap, mem, isValueList)) rval = ob + ".@" + mem.Name;
+							if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList)) rval = ob + ".@" + mem.Name;
 							WriteLine (mem.TypeData.FullTypeName + " " + flatLists[n] + " = " + rval + ";");
 							WriteLine (mem.TypeData.FullTypeName + " " + flatLists[n] + " = " + rval + ";");
 						}
 						}
 					}
 					}
@@ -1685,7 +1685,7 @@ namespace System.Xml.Serialization
 							RegisterReferencingMap (info.MappedType);
 							RegisterReferencingMap (info.MappedType);
 
 
 							WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");	// Already read
 							WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");	// Already read
-							if (IsReadOnly (typeMap, info.Member, isValueList)) 
+							if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
 								WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral(info.TypeData.FullTypeName) + ");");
 								WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral(info.TypeData.FullTypeName) + ");");
 							else 
 							else 
 								GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
 								GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
@@ -1694,7 +1694,7 @@ namespace System.Xml.Serialization
 							if (!info.MappedType.TypeData.Type.IsArray)
 							if (!info.MappedType.TypeData.Type.IsArray)
 							{
 							{
 								WriteLineInd ("else {");
 								WriteLineInd ("else {");
-								if (IsReadOnly (typeMap, info.Member, isValueList)) 
+								if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
 									WriteLine (list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
 									WriteLine (list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
 								else { 
 								else { 
 									WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
 									WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
@@ -1708,7 +1708,7 @@ namespace System.Xml.Serialization
 						else
 						else
 						{
 						{
 							if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
 							if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
-								if (IsReadOnly (typeMap, info.Member, isValueList)) GenerateReadListElement (info.MappedType, GenerateGetMemberValue (info.Member, ob, isValueList), GetLiteral(info.IsNullable), false);
+								if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) GenerateReadListElement (info.MappedType, GenerateGetMemberValue (info.Member, ob, isValueList), GetLiteral(info.IsNullable), false);
 								else GenerateSetMemberValue (info.Member, ob, GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true), isValueList);
 								else GenerateSetMemberValue (info.Member, ob, GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true), isValueList);
 								GenerateEndHook ();
 								GenerateEndHook ();
 							}
 							}
@@ -1720,7 +1720,7 @@ namespace System.Xml.Serialization
 					{
 					{
 						XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
 						XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
 						if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
 						if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
-							GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GenerateReadObjectElement (info), !IsReadOnly (typeMap, info.Member, isValueList));
+							GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GenerateReadObjectElement (info), !IsReadOnly (typeMap, info.Member, info.TypeData, isValueList));
 							GenerateEndHook ();
 							GenerateEndHook ();
 						}
 						}
 						WriteLine (indexes[mem.FlatArrayIndex] + "++;");
 						WriteLine (indexes[mem.FlatArrayIndex] + "++;");
@@ -1853,7 +1853,7 @@ namespace System.Xml.Serialization
 						string list = flatLists[mem.FlatArrayIndex];
 						string list = flatLists[mem.FlatArrayIndex];
 						if (mem.TypeData.Type.IsArray)
 						if (mem.TypeData.Type.IsArray)
 							WriteLine (list + " = (" + mem.TypeData.FullTypeName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.TypeData.Type.GetElementType()) + ", true);");
 							WriteLine (list + " = (" + mem.TypeData.FullTypeName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.TypeData.Type.GetElementType()) + ", true);");
-						if (!IsReadOnly (typeMap, mem, isValueList))
+						if (!IsReadOnly (typeMap, mem, mem.TypeData, isValueList))
 							GenerateSetMemberValue (mem, ob, list, isValueList);
 							GenerateSetMemberValue (mem, ob, list, isValueList);
 					}
 					}
 				}
 				}
@@ -1867,10 +1867,10 @@ namespace System.Xml.Serialization
 			}
 			}
 		}
 		}
 		
 		
-		bool IsReadOnly (XmlTypeMapping map, XmlTypeMapMember member, bool isValueList)
+		bool IsReadOnly (XmlTypeMapping map, XmlTypeMapMember member, TypeData memType, bool isValueList)
 		{
 		{
-			if (isValueList) return false;
-			else return member.IsReadOnly (map.TypeData.Type);
+			if (isValueList) return !memType.HasPublicConstructor;
+			else return member.IsReadOnly (map.TypeData.Type) || !memType.HasPublicConstructor;
 		}
 		}
 
 
 		void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
 		void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
@@ -1954,7 +1954,7 @@ namespace System.Xml.Serialization
 			Type listType = typeMap.TypeData.Type;
 			Type listType = typeMap.TypeData.Type;
 			ListMap listMap = (ListMap)typeMap.ObjectMap;
 			ListMap listMap = (ListMap)typeMap.ObjectMap;
 
 
-			if (canCreateInstance) 
+			if (canCreateInstance && typeMap.TypeData.HasPublicConstructor) 
 			{
 			{
 				list = GetObTempVar ();
 				list = GetObTempVar ();
 				WriteLine (typeMap.TypeFullName + " " + list + " = null;");
 				WriteLine (typeMap.TypeFullName + " " + list + " = null;");
@@ -1963,10 +1963,20 @@ namespace System.Xml.Serialization
 			}
 			}
 			else
 			else
 			{
 			{
-				WriteLineInd ("if (" + list + " == null)");
-				WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeFullName) + ");");
-				Unindent ();
-				WriteLineInd ("if (!ReadNull()) {");
+				if (list != null) {
+					WriteLineInd ("if (" + list + " == null)");
+					WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeFullName) + ");");
+					Unindent ();
+					WriteLineInd ("if (!ReadNull()) {");
+				}
+				else {
+					list = GetObTempVar ();
+					WriteLine (typeMap.TypeFullName + " " + list + " = null;");
+					WriteLineInd ("if (" + list + " == null)");
+					WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeFullName) + ");");
+					Unindent ();
+					return list;
+				}
 			}
 			}
 				
 				
 			WriteLineInd ("if (Reader.IsEmptyElement) {");
 			WriteLineInd ("if (Reader.IsEmptyElement) {");

+ 2 - 2
mcs/class/System.XML/System.Xml.Serialization/SoapReflectionImporter.cs

@@ -173,7 +173,7 @@ namespace System.Xml.Serialization {
 			if (type.IsValueType) throw CreateStructException (type);
 			if (type.IsValueType) throw CreateStructException (type);
 			if (type == typeof (object)) defaultNamespace = XmlSchema.Namespace;
 			if (type == typeof (object)) defaultNamespace = XmlSchema.Namespace;
 
 
-			ReflectionHelper.CheckSerializableType (type);
+			ReflectionHelper.CheckSerializableType (type, false);
 				
 				
 			TypeData typeData = TypeTranslator.GetTypeData (type);
 			TypeData typeData = TypeTranslator.GetTypeData (type);
 			XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, defaultNamespace));
 			XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, defaultNamespace));
@@ -333,7 +333,7 @@ namespace System.Xml.Serialization {
 			XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, defaultNamespace));
 			XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, defaultNamespace));
 			if (map != null) return map;
 			if (map != null) return map;
 			
 			
-			ReflectionHelper.CheckSerializableType (type);
+			ReflectionHelper.CheckSerializableType (type, false);
 				
 				
 			map = CreateTypeMapping (typeData, null, defaultNamespace);
 			map = CreateTypeMapping (typeData, null, defaultNamespace);
 			helper.RegisterClrType (map, type, map.Namespace);
 			helper.RegisterClrType (map, type, map.Namespace);

+ 11 - 0
mcs/class/System.XML/System.Xml.Serialization/TypeData.cs

@@ -45,6 +45,7 @@ namespace System.Xml.Serialization
 		string fullTypeName;
 		string fullTypeName;
 		TypeData listItemTypeData;
 		TypeData listItemTypeData;
 		TypeData listTypeData;
 		TypeData listTypeData;
+		bool hasPublicConstructor = true;
 
 
 		public TypeData (Type type, string elementName, bool isPrimitive)
 		public TypeData (Type type, string elementName, bool isPrimitive)
 		{
 		{
@@ -72,6 +73,10 @@ namespace System.Xml.Serialization
 				this.elementName = TypeTranslator.GetArrayName (ListItemTypeData.XmlType);
 				this.elementName = TypeTranslator.GetArrayName (ListItemTypeData.XmlType);
 			else
 			else
 				this.elementName = elementName;
 				this.elementName = elementName;
+
+			if (sType == SchemaTypes.Array || sType == SchemaTypes.Class) {
+				hasPublicConstructor = (type.IsArray || type.GetConstructor (Type.EmptyTypes) != null || type.IsAbstract || type.IsValueType);
+			}
 		}
 		}
 
 
 		internal TypeData (string typeName, string fullTypeName, string xmlType, SchemaTypes schemaType, TypeData listItemTypeData)
 		internal TypeData (string typeName, string fullTypeName, string xmlType, SchemaTypes schemaType, TypeData listItemTypeData)
@@ -81,6 +86,7 @@ namespace System.Xml.Serialization
 			this.fullTypeName = fullTypeName.Replace ('+', '.');
 			this.fullTypeName = fullTypeName.Replace ('+', '.');
 			this.listItemTypeData = listItemTypeData;
 			this.listItemTypeData = listItemTypeData;
 			this.sType = schemaType;
 			this.sType = schemaType;
+			this.hasPublicConstructor = true;
 		}
 		}
 
 
 		public string TypeName
 		public string TypeName
@@ -206,6 +212,11 @@ namespace System.Xml.Serialization
 				return listTypeData;
 				return listTypeData;
 			}
 			}
 		}
 		}
+		
+		public bool HasPublicConstructor
+		{
+			get { return hasPublicConstructor; }
+		}
 
 
 
 
 		public static PropertyInfo GetIndexerProperty (Type collectionType)
 		public static PropertyInfo GetIndexerProperty (Type collectionType)

+ 4 - 4
mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs

@@ -256,7 +256,7 @@ namespace System.Xml.Serialization {
 			if (map != null) return map;
 			if (map != null) return map;
 
 
 			if (!allowPrivateTypes)
 			if (!allowPrivateTypes)
-				ReflectionHelper.CheckSerializableType (type);
+				ReflectionHelper.CheckSerializableType (type, false);
 			
 			
 			map = CreateTypeMapping (typeData, root, null, defaultNamespace);
 			map = CreateTypeMapping (typeData, root, null, defaultNamespace);
 			helper.RegisterClrType (map, type, map.XmlTypeNamespace);
 			helper.RegisterClrType (map, type, map.XmlTypeNamespace);
@@ -380,7 +380,7 @@ namespace System.Xml.Serialization {
 			ListMap obmap = new ListMap ();
 			ListMap obmap = new ListMap ();
 
 
 			if (!allowPrivateTypes)
 			if (!allowPrivateTypes)
-				ReflectionHelper.CheckSerializableType (type);
+				ReflectionHelper.CheckSerializableType (type, true);
 			
 			
 			if (atts == null) atts = new XmlAttributes();
 			if (atts == null) atts = new XmlAttributes();
 			Type itemType = typeData.ListItemType;
 			Type itemType = typeData.ListItemType;
@@ -528,7 +528,7 @@ namespace System.Xml.Serialization {
 			if (map != null) return map;
 			if (map != null) return map;
 			
 			
 			if (!allowPrivateTypes)
 			if (!allowPrivateTypes)
-				ReflectionHelper.CheckSerializableType (type);
+				ReflectionHelper.CheckSerializableType (type, false);
 				
 				
 			map = CreateTypeMapping (typeData, root, null, defaultNamespace);
 			map = CreateTypeMapping (typeData, root, null, defaultNamespace);
 			helper.RegisterClrType (map, type, map.XmlTypeNamespace);
 			helper.RegisterClrType (map, type, map.XmlTypeNamespace);
@@ -560,7 +560,7 @@ namespace System.Xml.Serialization {
 			if (map != null) return map;
 			if (map != null) return map;
 			
 			
 			if (!allowPrivateTypes)
 			if (!allowPrivateTypes)
-				ReflectionHelper.CheckSerializableType (type);
+				ReflectionHelper.CheckSerializableType (type, false);
 				
 				
 			map = CreateTypeMapping (typeData, root, null, defaultNamespace);
 			map = CreateTypeMapping (typeData, root, null, defaultNamespace);
 			helper.RegisterClrType (map, type, map.XmlTypeNamespace);
 			helper.RegisterClrType (map, type, map.XmlTypeNamespace);

+ 10 - 10
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs

@@ -316,7 +316,7 @@ namespace System.Xml.Serialization
 				indexes = new int[map.FlatLists.Count];
 				indexes = new int[map.FlatLists.Count];
 				flatLists = new object[map.FlatLists.Count];
 				flatLists = new object[map.FlatLists.Count];
 				foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
 				foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
-					if (IsReadOnly (mem, ob, isValueList)) flatLists[mem.FlatArrayIndex] = mem.GetValue (ob);
+					if (IsReadOnly (mem, mem.TypeData, ob, isValueList)) flatLists[mem.FlatArrayIndex] = mem.GetValue (ob);
 			}
 			}
 			
 			
 			if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
 			if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
@@ -351,12 +351,12 @@ namespace System.Xml.Serialization
 								object list = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
 								object list = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
 								if (fixup.Ids[info.Member.Index] == null)	// Already read
 								if (fixup.Ids[info.Member.Index] == null)	// Already read
 								{
 								{
-									if (IsReadOnly (info.Member, ob, isValueList)) throw CreateReadOnlyCollectionException (info.TypeData.FullTypeName);
+									if (IsReadOnly (info.Member, info.TypeData, ob, isValueList)) throw CreateReadOnlyCollectionException (info.TypeData.FullTypeName);
 									else SetMemberValue (info.Member, ob, list, isValueList);
 									else SetMemberValue (info.Member, ob, list, isValueList);
 								}
 								}
 								else if (!info.MappedType.TypeData.Type.IsArray)
 								else if (!info.MappedType.TypeData.Type.IsArray)
 								{
 								{
-									if (IsReadOnly (info.Member, ob, isValueList)) 
+									if (IsReadOnly (info.Member, info.TypeData, ob, isValueList)) 
 										list = GetMemberValue (info.Member, ob, isValueList);
 										list = GetMemberValue (info.Member, ob, isValueList);
 									else { 
 									else { 
 										list = CreateList (info.MappedType.TypeData.Type);
 										list = CreateList (info.MappedType.TypeData.Type);
@@ -368,7 +368,7 @@ namespace System.Xml.Serialization
 							}
 							}
 							else
 							else
 							{
 							{
-								if (IsReadOnly (info.Member, ob, isValueList)) ReadListElement (info.MappedType, info.IsNullable, GetMemberValue (info.Member, ob, isValueList), false);
+								if (IsReadOnly (info.Member, info.TypeData, ob, isValueList)) ReadListElement (info.MappedType, info.IsNullable, GetMemberValue (info.Member, ob, isValueList), false);
 								else SetMemberValue (info.Member, ob, ReadListElement (info.MappedType, info.IsNullable, null, true), isValueList);
 								else SetMemberValue (info.Member, ob, ReadListElement (info.MappedType, info.IsNullable, null, true), isValueList);
 							}
 							}
 							readFlag[info.Member.Index] = true;
 							readFlag[info.Member.Index] = true;
@@ -376,7 +376,7 @@ namespace System.Xml.Serialization
 						else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
 						else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
 						{
 						{
 							XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
 							XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
-							AddListValue (mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadObjectElement (info), !IsReadOnly (info.Member, ob, isValueList));
+							AddListValue (mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadObjectElement (info), !IsReadOnly (info.Member, info.TypeData, ob, isValueList));
 						}
 						}
 						else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
 						else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
 						{
 						{
@@ -447,7 +447,7 @@ namespace System.Xml.Serialization
 					Object list = flatLists[mem.FlatArrayIndex];
 					Object list = flatLists[mem.FlatArrayIndex];
 					if (mem.TypeData.Type.IsArray)
 					if (mem.TypeData.Type.IsArray)
 						list = ShrinkArray ((Array)list, indexes[mem.FlatArrayIndex], mem.TypeData.Type.GetElementType(), true);
 						list = ShrinkArray ((Array)list, indexes[mem.FlatArrayIndex], mem.TypeData.Type.GetElementType(), true);
-					if (!IsReadOnly (mem, ob, isValueList))
+					if (!IsReadOnly (mem, mem.TypeData, ob, isValueList))
 						SetMemberValue (mem, ob, list, isValueList);
 						SetMemberValue (mem, ob, list, isValueList);
 				}
 				}
 			}		
 			}		
@@ -475,10 +475,10 @@ namespace System.Xml.Serialization
 			UnknownNode (target);
 			UnknownNode (target);
 		}
 		}
 
 
-		bool IsReadOnly (XmlTypeMapMember member, object ob, bool isValueList)
+		bool IsReadOnly (XmlTypeMapMember member, TypeData memType, object ob, bool isValueList)
 		{
 		{
-			if (isValueList) return false;
-			else return member.IsReadOnly (ob.GetType());
+			if (isValueList) return !memType.HasPublicConstructor;
+			else return member.IsReadOnly (ob.GetType()) || !memType.HasPublicConstructor;
 		}
 		}
 
 
 		void SetMemberValue (XmlTypeMapMember member, object ob, object value, bool isValueList)
 		void SetMemberValue (XmlTypeMapMember member, object ob, object value, bool isValueList)
@@ -566,7 +566,7 @@ namespace System.Xml.Serialization
 			if (ReadNull()) return null;
 			if (ReadNull()) return null;
 
 
 			if (list == null) {
 			if (list == null) {
-				if (canCreateInstance) list = CreateList (listType);
+				if (canCreateInstance && typeMap.TypeData.HasPublicConstructor) list = CreateList (listType);
 				else throw CreateReadOnlyCollectionException (typeMap.TypeFullName);
 				else throw CreateReadOnlyCollectionException (typeMap.TypeFullName);
 			}
 			}