Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/6.0-rc2] XmlSerializer support for IsDynamicCodeSupported=false #59507

Merged
merged 5 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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)
{
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<ItemGroup>
<TestConsoleAppSourceFiles Include="XmlSchema.Write.cs" />
<TestConsoleAppSourceFiles Include="XmlSerializer.Deserialize.cs" />
<TestConsoleAppSourceFiles Include="XmlSerializer.Deserialize.SealerOpt.cs"
ExtraTrimmerArgs="--enable-opt sealer" />
<TestConsoleAppSourceFiles Include="XmlSerializer.Serialize.cs" />
<TestConsoleAppSourceFiles Include="XslCompiledTransformTests.cs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Tests that using XmlSerializer with linker option '--enable-opt sealer' works
/// when IsDynamicCodeSupported==false.
/// </summary>
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(@"<?xml version=""1.0"" encoding=""UTF-8""?>
<Response DataType=""Data"">
</Response>");

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; }
}
}