Skip to content

Fix legacy generic dictionary conversion#12116

Draft
simonrozsival wants to merge 1 commit into
mainfrom
dev/simonrozsival/fix-legacy-valuemanager-dictionaries
Draft

Fix legacy generic dictionary conversion#12116
simonrozsival wants to merge 1 commit into
mainfrom
dev/simonrozsival/fix-legacy-valuemanager-dictionaries

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Summary

Experimental coverage of all 400 key/value combinations across primitive, nullable primitive, string, and Java peer types showed that JavaConvert.FromJniHandle(Type) produces the exact requested JavaDictionary<TKey,TValue>, while reflection-backed value managers reused a cached non-generic JavaDictionary and GetValue<T> then failed with InvalidCastException.

This change makes both legacy reflection-backed Android value managers honor explicit closed IDictionary<TKey,TValue> and JavaDictionary<TKey,TValue> targets by routing them through the existing JavaConvert generic collection factory. It also teaches the dynamic factory path to accept an explicit JavaDictionary<TKey,TValue> target.

Compatibility

  • Java-to-managed default type inference is unchanged because only explicit closed generic dictionary targets take the new path.
  • Non-generic IDictionary conversion remains unchanged.
  • JavaConvert returns an already cached peer when it is assignable to the requested type, preserving peer identity.
  • The implementation uses the existing reflection-backed generic collection factory and introduces no new arbitrary trimming roots.

Tests

Added representative device coverage for:

  • primitive/string IDictionary<int, string>
  • nullable primitive JavaDictionary<int?, double?>
  • string/Java peer IDictionary<string, MyIntent>
  • Java peer/nullable primitive JavaDictionary<MyIntent, long?>
  • non-generic dictionary behavior
  • assignable cached generic peer identity

Validation:

  • make all CONFIGURATION=Debug
  • dotnet build src/Mono.Android/Mono.Android.csproj -c Debug --no-restore
  • dotnet test external/Java.Interop/tests/Java.Interop-Tests/Java.Interop-Tests.csproj -c Debug (670 passed, 6 skipped)
  • on-device Mono.Android.NET-Tests (918 passed, 55 skipped)

The 400-case result is the experimental motivating matrix; the committed regression suite intentionally uses representative shapes rather than duplicating all 400 combinations.

Route requested generic dictionary targets through JavaConvert while preserving assignable cached peers and non-generic inference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0e043be9-9070-43bc-aea4-a48438690bdf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant