diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs
index 15d78f2896ae62..20f9d18343cbb8 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs
@@ -194,7 +194,10 @@ public XmlSerializer(XmlTypeMapping xmlTypeMapping)
if (xmlTypeMapping == null)
throw new ArgumentNullException(nameof(xmlTypeMapping));
- _tempAssembly = GenerateTempAssembly(xmlTypeMapping);
+ if (Mode != SerializationMode.ReflectionOnly)
+ {
+ _tempAssembly = GenerateTempAssembly(xmlTypeMapping);
+ }
_mapping = xmlTypeMapping;
}
@@ -218,6 +221,12 @@ public XmlSerializer(Type type, string? defaultNamespace)
_primitiveType = type;
return;
}
+
+ if (Mode == SerializationMode.ReflectionOnly)
+ {
+ return;
+ }
+
_tempAssembly = s_cache[defaultNamespace, type];
if (_tempAssembly == null)
{
@@ -270,7 +279,10 @@ public XmlSerializer(Type type, XmlAttributeOverrides? overrides, Type[]? extraT
DefaultNamespace = defaultNamespace;
_rootType = type;
_mapping = GenerateXmlTypeMapping(type, overrides, extraTypes, root, defaultNamespace);
- _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace, location);
+ if (Mode != SerializationMode.ReflectionOnly)
+ {
+ _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace, location);
+ }
}
[RequiresUnreferencedCode("calls ImportTypeMapping")]
@@ -530,6 +542,14 @@ public virtual bool CanDeserialize(XmlReader xmlReader)
TypeDesc typeDesc = (TypeDesc)TypeScope.PrimtiveTypes[_primitiveType]!;
return xmlReader.IsStartElement(typeDesc.DataType!.Name!, string.Empty);
}
+ else if (ShouldUseReflectionBasedSerialization(_mapping) || _isReflectionBasedSerializer)
+ {
+ // If we should use reflection, we will try to do reflection-based deserialization, without fallback.
+ // Don't check xmlReader.IsStartElement to avoid having to duplicate SOAP deserialization logic here.
+ // It is better to return an incorrect 'true', which will throw during Deserialize than to return an
+ // incorrect 'false', and the caller won't even try to Deserialize when it would succeed.
+ return true;
+ }
else if (_tempAssembly != null)
{
return _tempAssembly.CanRead(_mapping, xmlReader);
diff --git a/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj b/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj
index d7a0e73f68f5b8..181be44826a6a6 100644
--- a/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj
+++ b/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj
@@ -4,6 +4,8 @@
+
diff --git a/src/libraries/System.Private.Xml/tests/TrimmingTests/XmlSerializer.Deserialize.SealerOpt.cs b/src/libraries/System.Private.Xml/tests/TrimmingTests/XmlSerializer.Deserialize.SealerOpt.cs
new file mode 100644
index 00000000000000..11a5b5e91827f4
--- /dev/null
+++ b/src/libraries/System.Private.Xml/tests/TrimmingTests/XmlSerializer.Deserialize.SealerOpt.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Reflection;
+
+namespace System.Xml.Serialization.TrimmingTests
+{
+ ///
+ /// Tests that using XmlSerializer with linker option '--enable-opt sealer' works
+ /// when IsDynamicCodeSupported==false.
+ ///
+ internal class Program
+ {
+ // Preserve these types until XmlSerializer is fully trim-safe.
+ // see https://github.com/dotnet/runtime/issues/44768
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Response))]
+ public static int Main()
+ {
+ // simulate IsDynamicCodeSupported==false by setting the SerializationMode to ReflectionOnly
+ const int ReflectionOnly = 1;
+ typeof(XmlSerializer).GetField("s_mode", BindingFlags.NonPublic | BindingFlags.Static)
+ .SetValue(null, ReflectionOnly);
+
+ using StringReader stringReader = new StringReader(@"
+
+ ");
+
+ Response obj = (Response)new XmlSerializer(typeof(Response)).Deserialize(stringReader);
+ if (obj.DataType == "Data")
+ {
+ return 100;
+ }
+
+ return -1;
+ }
+ }
+
+ [Serializable]
+ [XmlType(AnonymousType = true)]
+ [XmlRoot(Namespace = "", IsNullable = false)]
+ public class Response
+ {
+ [XmlAttribute]
+ public string DataType { get; set; }
+ }
+}