diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs
index 0c08561ba20ced..ba7ea685facfb8 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs
@@ -1576,9 +1576,7 @@ private static XmlSerializationCollectionFixupCallback GetCreateCollectionOfObje
{
if (structMapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(structMapping.TypeDesc.Type))
{
- // https://github.com/dotnet/runtime/issues/1399:
- // To Support Serializing XmlSchemaObject
- throw new NotImplementedException(nameof(XmlSchemaObject));
+ DecodeName = false;
}
object? o = ReflectionCreateObject(structMapping.TypeDesc.Type!)!;
@@ -1812,10 +1810,24 @@ private static XmlSerializationCollectionFixupCallback GetCreateCollectionOfObje
{
MemberInfo[] memberInfos = o!.GetType().GetMember(member.Mapping.Name);
MemberInfo memberInfo = memberInfos[0];
- object? collection = null;
- SetCollectionObjectWithCollectionMember(ref collection, member.Collection, member.Mapping.TypeDesc!.Type!);
- var setMemberValue = GetSetMemberValueDelegate(o, memberInfo.Name);
- setMemberValue(o, collection);
+
+ // For read-only collection properties (no setter), add items directly to the existing
+ // collection instance returned by the getter. This matches what the IL-based serializer does.
+ if (memberInfo is PropertyInfo pi && pi.GetSetMethod(nonPublic: true) == null)
+ {
+ object? existingCollection = pi.GetValue(o);
+ if (existingCollection != null)
+ {
+ AddObjectsIntoTargetCollection(existingCollection, member.Collection, member.Mapping.TypeDesc!.Type!);
+ }
+ }
+ else
+ {
+ object? collection = null;
+ SetCollectionObjectWithCollectionMember(ref collection, member.Collection, member.Mapping.TypeDesc!.Type!);
+ var setMemberValue = GetSetMemberValueDelegate(o, memberInfo.Name);
+ setMemberValue(o, collection);
+ }
}
member.EnsureCollection?.Invoke(o!);
diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.Internal.cs b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.Internal.cs
index 733b5ae83c1952..1178edc4606fc1 100644
--- a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.Internal.cs
+++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.Internal.cs
@@ -76,39 +76,4 @@ public static void XML_TypeWithFieldsOrdered()
Assert.Equal(value.StringField1, actual.StringField1);
Assert.Equal(value.StringField2, actual.StringField2);
}
-
- // TODO - Move this test to XmlSerializerTests.RuntimeOnly.cs once #1399 is fixed for the ReflectionOnly serializer.
- [Fact]
- public static void Xml_XmlSchema()
- {
- var expectedXml = WithXmlHeader("\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n");
-
- XmlSchema schema = new XmlSchema
- {
- TargetNamespace = "http://example.com/my-schema",
- ElementFormDefault = XmlSchemaForm.Qualified
- };
- schema.Items.Add(new XmlSchemaElement
- {
- Name = "MyElement",
- SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")
- });
- schema.Items.Add(new XmlSchemaGroup
- {
- Name = "MyGroup",
- Particle = new XmlSchemaSequence
- {
- Items = { new XmlSchemaElement { Name = "Item1" }, new XmlSchemaElement { Name = "Item2" } }
- }
- });
- schema.Namespaces.Add("xsd", "http://www.w3.org/2001/XMLSchema");
- schema.Namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
-
- var actual = SerializeAndDeserialize(schema, expectedXml, () => new XmlSerializer(typeof(XmlSchema)));
-
- Assert.Equal(schema.TargetNamespace, actual.TargetNamespace);
- Assert.Equal(schema.ElementFormDefault, actual.ElementFormDefault);
- Assert.Equal(schema.Items.Count, actual.Items.Count);
- }
-
}
diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs
index 07f0e6816fb2d0..441f35bf87a7fb 100644
--- a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs
+++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.RuntimeOnly.cs
@@ -861,6 +861,81 @@ public static void XML_XmlSchemaWithNamespacesWriteWithNamespaceManager()
schema.Write(memStream, new XmlNamespaceManager(new NameTable()));
}
+ [Fact]
+ public static void Xml_XmlSchema()
+ {
+ var expectedXml = WithXmlHeader("\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n");
+
+ XmlSchema schema = new XmlSchema
+ {
+ TargetNamespace = "http://example.com/my-schema",
+ ElementFormDefault = XmlSchemaForm.Qualified
+ };
+ schema.Items.Add(new XmlSchemaElement
+ {
+ Name = "MyElement",
+ SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")
+ });
+ schema.Items.Add(new XmlSchemaGroup
+ {
+ Name = "MyGroup",
+ Particle = new XmlSchemaSequence
+ {
+ Items = { new XmlSchemaElement { Name = "Item1" }, new XmlSchemaElement { Name = "Item2" } }
+ }
+ });
+ schema.Namespaces.Add("xsd", "http://www.w3.org/2001/XMLSchema");
+ schema.Namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+
+ var actual = SerializeAndDeserialize(schema, expectedXml, () => new XmlSerializer(typeof(XmlSchema)));
+
+ Assert.Equal(schema.TargetNamespace, actual.TargetNamespace);
+ Assert.Equal(schema.ElementFormDefault, actual.ElementFormDefault);
+ Assert.Equal(schema.Items.Count, actual.Items.Count);
+ }
+
+ [Fact]
+ public static void XmlSchemaObject_RoundTrip()
+ {
+ // Verify that XmlSchemaObject-derived types can be deserialized with the reflection-based
+ // serializer. Previously a NotImplementedException was thrown during deserialization.
+ var element = new XmlSchemaElement
+ {
+ Name = "TestElement",
+ SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")
+ };
+ var serializer = new XmlSerializer(typeof(XmlSchemaElement));
+ using var ms = new MemoryStream();
+ serializer.Serialize(ms, element);
+ ms.Position = 0;
+
+ var result = (XmlSchemaElement?)serializer.Deserialize(ms);
+ Assert.NotNull(result);
+ Assert.Equal("TestElement", result.Name);
+ Assert.Equal(new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema"), result.SchemaTypeName);
+ }
+
+ [Fact]
+ public static void XmlSchemaObject_RoundTrip_WithConstraintInReadOnlyCollection()
+ {
+ // Verify that items in read-only collection properties (like XmlSchemaElement.Constraints)
+ // are correctly round-tripped using the reflection-based serializer.
+ var element = new XmlSchemaElement { Name = "TestElement" };
+ element.Constraints.Add(new XmlSchemaKey { Name = "PrimaryKey" });
+
+ var serializer = new XmlSerializer(typeof(XmlSchemaElement));
+ using var ms = new MemoryStream();
+ serializer.Serialize(ms, element);
+ ms.Position = 0;
+
+ var result = (XmlSchemaElement?)serializer.Deserialize(ms);
+ Assert.NotNull(result);
+ Assert.Equal("TestElement", result.Name);
+ Assert.Equal(1, result.Constraints.Count);
+ var key = Assert.IsType(result.Constraints[0]);
+ Assert.Equal("PrimaryKey", key.Name);
+ }
+
[Fact]
public static void Xml_XmlElementAsRoot()
{