fix: enforce no-throw contract in Reflector.Try* APIs (PR #71 follow-ups)#76
Merged
Conversation
…ups) Address 7 unresolved review threads from copilot-pull-request-reviewer on PR #71. The Try* methods (TryPatch, TryModifyAt, TryReadAt, View) all document "errors accumulated in the optional Logs object; nothing is thrown", but several reflection call sites could let exceptions escape on write-only properties, throwing getters/setters, missing converters, or null patches against non-nullable value types. Reflector.Patch.cs: - TryPatchInternal: guard the JSON-null patch path against non-nullable value-type targets (Nullable<T> still permits null) — previously the null would propagate to a SetValue that throws ArgumentException. - TryPatchInternal: wrap CreateInstance in try/catch — Reflector.DefaultValue documents that it throws ArgumentException when no converter supports the type. - TryPatchMember: add CanRead check on properties; wrap field/property GetValue and SetValue in try/catch with logged failures. Reflector.Navigate.cs: - TryLookupMember: add CanRead check on properties; wrap field/property GetValue and SetValue in try/catch. - TryLookupMember: switch the "Available fields/properties" error list from raw GetFields/GetProperties to GetSerializableFields/Properties so the message matches what Serialize/TryModify actually operate on (matches the existing convention in TryNavigateOneSegment and BaseReflectionConverter). Drop `static` on TryLookupMember to access the instance helpers — its only caller (TryModifyAtMember) is already an instance method. Reflector.ReadAt.cs: - TryNavigateOneSegment: add CanRead check on properties; wrap field/ property GetValue in try/catch with logged failures. Reflector.View.cs: - View: wrap the Serialize call in try/catch(ArgumentException) — Serialize is documented to throw when both obj and fallbackObjType are null or no converter exists for the resolved type. Mirrors the existing TryCompilePattern try/catch convention in the same file. Tests: 1423/1423 pass on net8.0 and net9.0 (no test changes — these fixes plug exception leaks that the existing suite did not exercise).
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Address 7 unresolved review threads from
copilot-pull-request-revieweron the merged PR #71. TheTry*methods (TryPatch,TryModifyAt,TryReadAt,View) all document "errors accumulated in the optional Logs object; nothing is thrown", but several reflection call sites could let exceptions escape on write-only properties, throwing getters/setters, missing converters, ornullpatches applied to non-nullable value types.This PR plugs all 7 leaks. No public API surface change; behaviour change is strictly: paths that previously threw now log and return
false/null.Changes per file
Reflector.Patch.csTryPatchInternal— guard the JSON-nullpatch path against non-nullable value-type targets (Nullable<T>still permitsnull). Previously thenullwould propagate to aSetValuethat throwsArgumentException. (Thread #2930803248)TryPatchInternal— wrapCreateInstancein try/catch.Reflector.DefaultValuedocuments thatCreateInstancethrowsArgumentExceptionwhen no converter supports the type. (Thread #2930803081)TryPatchMember— addCanReadcheck on properties; wrap field/propertyGetValueandSetValuein try/catch with logged failures. (Thread #2930803137)Reflector.Navigate.csTryLookupMember— addCanReadcheck on properties; wrap field/propertyGetValueandSetValuein try/catch. (Thread #2930803150)TryLookupMember— switch the "Available fields/properties" error list from rawGetFields/GetPropertiestoGetSerializableFields/Propertiesso the message matches whatSerialize/TryModifyactually operate on (matches the existing convention inTryNavigateOneSegmentandBaseReflectionConverter.GetCachedSerializableMemberNames). DropsstaticonTryLookupMemberto access the instance helpers — its only caller (TryModifyAtMember) is already an instance method, so the change is signature-compatible. (Thread #2930803173)Reflector.ReadAt.csTryNavigateOneSegment— addCanReadcheck on properties; wrap field/propertyGetValuein try/catch with logged failures. (Thread #2930803191)Reflector.View.csView— wrap theSerializecall intry/catch(ArgumentException).Serializeis documented to throw when bothobjandfallbackObjTypeare null, or when no converter exists for the resolved type. Mirrors the existingTryCompilePatterntry/catch convention in the same file. (Thread #2930803221)Test plan
dotnet build --configuration Release— 0 warnings, 0 errors acrossnetstandard2.1,net8.0,net9.0.dotnet test --configuration Release— 1423/1423 pass onnet8.0andnet9.0. No test changes — these fixes plug exception leaks that the existing suite did not exercise.int, missing converter onCreateInstance). Out of scope here; can land in a separate PR.Notes
Try*methods retain theirbool/ nullable return signature — no API surface change.catchlogs to the suppliedLogs?and to theILogger?(whenLogLevel.Erroris enabled), matching the existing pattern in this file.