Skip to content

Fix CheckSpecified setter for field-backed members in ReflectionXmlSerializationReader#126035

Merged
StephenMolloy merged 4 commits intodotnet:mainfrom
haltandcatchwater:fix-reader-checkspecified-reflection
Apr 25, 2026
Merged

Fix CheckSpecified setter for field-backed members in ReflectionXmlSerializationReader#126035
StephenMolloy merged 4 commits intodotnet:mainfrom
haltandcatchwater:fix-reader-checkspecified-reflection

Conversation

@haltandcatchwater
Copy link
Copy Markdown
Contributor

@haltandcatchwater haltandcatchwater commented Mar 24, 2026

Summary

ReflectionXmlSerializationReader
This pull request improves the XML serialization and deserialization logic by optimizing how "ShouldSerialize" and "Specified" members are handled, and adds new tests to ensure correct behavior for inherited serialization methods and field-backed "Specified" members.

Serialization and Deserialization Logic Improvements:

  • Refactored the invocation of "ShouldSerialize" methods by using cached MethodInfo instances (CheckShouldPersistMethodInfo) instead of repeated reflection lookups, improving performance and maintainability. [1] [2]
  • Updated the mechanism for setting "Specified" members during deserialization to use a delegate (GetSetMemberValueDelegate) rather than reflection on every call, making the process more efficient and robust.

Test Coverage Enhancements:

  • Added new test cases to verify correct serialization and deserialization behavior for types with inherited "ShouldSerialize" methods, ensuring that inherited logic is respected. [1] [2]
  • Added a test for types with field-backed "Specified" members to confirm that these are correctly set during deserialization. [1] [2]

Test Types Additions:

  • Introduced new test types: BaseTypeWithShouldSerializeMethod, DerivedTypeWithInheritedShouldSerialize, and TypeWithFieldBackedSpecifiedMember to support the above tests.used GetMethod("set_X") to set XxxSpecified members during deserialization. This only finds property setters — for field-backed Specified members, GetMethod returns null and the setter is silently skipped, leaving the Specified flag as false even when the element is present in the XML.

The rest of the reflection reader already uses GetSetMemberValueDelegate (which handles both fields and properties and caches the delegate). The ILGen reader handles both via ILGenSet. This was the only call site using the raw GetMethod("set_X") pattern.

Related to #125859 (same class of reflection-path drift from the ILGen path).

Changes

  • ReflectionXmlSerializationReader.cs: Replace GetMethod("set_X") + ?.Invoke with GetSetMemberValueDelegate, resolving once and caching
  • SerializationTypes.cs: Add TypeWithFieldBackedSpecifiedMember with a public bool FooSpecified field
  • XmlSerializerTests.cs: Add test verifying FooSpecified is set to true after round-trip deserialization

…herited ShouldSerialize methods

ReflectionXmlSerializationWriter used BindingFlags.DeclaredOnly when
looking up ShouldSerialize methods at two call sites, which prevented
finding methods declared on base classes. This caused a
NullReferenceException when serializing derived types whose base class
defines the ShouldSerialize method.

The MemberMapping already stores the correctly resolved MethodInfo
(CheckShouldPersistMethodInfo), which is resolved without DeclaredOnly
during import and used by the IL-gen path. Use it directly in the
reflection path to match the IL-gen behavior.

Fix dotnet#120561
…ld-backed members

ReflectionXmlSerializationReader used GetMethod("set_X") to set
XxxSpecified members during deserialization. This only finds property
setters, silently skipping field-backed Specified members. The rest of
the reflection reader uses GetSetMemberValueDelegate which handles
both fields and properties and caches the delegate.

Replace the GetMethod call with GetSetMemberValueDelegate to align
with the existing pattern and fix deserialization of types with
field-backed Specified members.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes reflection-based XmlSerializer deserialization so XxxSpecified members are correctly set for both property- and field-backed patterns, aligning the reflection path with existing cached delegate infrastructure and the ILGen path.

Changes:

  • Update ReflectionXmlSerializationReader to set *Specified via GetSetMemberValueDelegate (supports fields + caching).
  • Add a new serialization test type with a field-backed FooSpecified member.
  • Add/extend XmlSerializer tests to cover field-backed *Specified and inherited ShouldSerialize* behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs Uses cached member-setter delegates to set XxxSpecified reliably for fields and properties during deserialization.
src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs Uses pre-resolved CheckShouldPersistMethodInfo instead of doing a GetMethod(...) lookup at write time.
src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs Adds test model types for inherited ShouldSerialize* and field-backed FooSpecified.
src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs Adds tests validating inherited ShouldSerialize* behavior and that field-backed FooSpecified is set on deserialize.

Copy link
Copy Markdown
Member

@StephenMolloy StephenMolloy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the updated "Expected" generated serializer code to include the new types in SerializationTypes.

Otherwise, lgtm

@StephenMolloy StephenMolloy self-assigned this Apr 25, 2026
@StephenMolloy
Copy link
Copy Markdown
Member

/ba-g unrelated test failure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Serialization community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants