-
Notifications
You must be signed in to change notification settings - Fork 566
Description
Updated Analysis: Generic Invoker Types Are Not a Real Problem
Original Concern
The legacy GetInvokerType has a MakeGenericType path for generic C# types. The concern was that the trimmable type map would not handle this.
Investigation Result: All Android invokers are non-generic C# types
Java uses type erasure for generics. The Mono.Android binding generator reflects this — all generated interfaces and their invokers are non-generic C# types, even when the Java type has generic parameters:
// java.util.Iterator<E> → non-generic C# interface + non-generic invoker
[Register("java/util/Iterator", "", "Java.Util.IIteratorInvoker")]
[JavaTypeParameters(new string[] {"E"})] // metadata only, not a C# generic param
public partial interface IIterator : IJavaObject, IJavaPeerable { ... }
[Register("java/util/Iterator", DoNotGenerateAcw=true)]
internal partial class IIteratorInvoker : Java.Lang.Object, IIterator { ... }The same pattern applies to all 90+ generic Java interfaces:
java/util/List→IList+IListInvoker(non-generic)java/util/Map→IMap+IMapInvoker(non-generic)android/os/Parcelable$Creator→IParcelableCreator+IParcelableCreatorInvoker(non-generic)- etc.
Runtime Flow (Legacy)
- Java returns an object implementing
java.util.Iterator GetJavaToManagedType("java/util/Iterator")→Java.Util.IIterator(non-generic)- Since
IIteratoris an interface,GetInvokerType(typeof(IIterator))is called IIteratorhas zero generic arguments → takes the simple path:Assembly.GetType("Java.Util.IIteratorInvoker")IIteratorInvokeris instantiated — noMakeGenericTypeinvolved
The MakeGenericType Path Is Dead Code (for Android)
The generic invoker resolution in JavaObjectExtensions.GetInvokerType (lines 137-146) and ManagedTypeManager.GetInvokerTypeCore (lines 48-59) handles C# generics like IFoo<T> → IFooInvoker<T>. But:
- No generated Mono.Android binding produces generic C# invoker types
- No Java.Interop or Java.Base types produce generic C# invoker types
- The code appears to be defensive/future-proofing for a pattern not currently used
Impact on Trimmable Type Map
Low to none. The trimmable path stores InvokerType as a pre-resolved non-generic type reference in the proxy attribute. Since all invokers in Mono.Android are non-generic, this works correctly:
TypeMap entry: "java/util/Iterator" → IIterator_Proxy
IIterator_Proxy.InvokerType → typeof(IIteratorInvoker) // non-generic, resolves fine
Recommendation
This issue can be deprioritized or closed. The generic invoker scenario is theoretical — it would only matter if:
- A third-party binding library creates actual C# generic interfaces (not just
[JavaTypeParameters]) - Someone uses the Java.Interop
[JniTypeSignature]pattern with generic C# types
Neither scenario is common or blocking for .NET 11.