@@ -16,7 +16,7 @@ public class TypeMappingStep : BaseStep
16
16
{
17
17
const string AssemblyName = "Microsoft.Android.Runtime.NativeAOT" ;
18
18
const string TypeName = "Microsoft.Android.Runtime.NativeAotTypeManager" ;
19
- readonly IDictionary < string , TypeDefinition > TypeMappings = new Dictionary < string , TypeDefinition > ( StringComparer . Ordinal ) ;
19
+ readonly IDictionary < string , List < TypeDefinition > > TypeMappings = new Dictionary < string , List < TypeDefinition > > ( StringComparer . Ordinal ) ;
20
20
AssemblyDefinition ? MicrosoftAndroidRuntimeNativeAot ;
21
21
22
22
protected override void ProcessAssembly ( AssemblyDefinition assembly )
@@ -66,7 +66,7 @@ protected override void EndProcess ()
66
66
var il = method . Body . GetILProcessor ( ) ;
67
67
var addMethod = module . ImportReference ( typeof ( IDictionary < string , Type > ) . GetMethod ( "Add" ) ) ;
68
68
var getTypeFromHandle = module . ImportReference ( typeof ( Type ) . GetMethod ( "GetTypeFromHandle" ) ) ;
69
- foreach ( var ( javaKey , typeDefinition ) in TypeMappings ) {
69
+ foreach ( var ( javaName , list ) in TypeMappings ) {
70
70
/*
71
71
* IL_0000: ldarg.0
72
72
* IL_0001: ldfld class [System.Runtime]System.Collections.Generic.IDictionary`2<string, class [System.Runtime]System.Type> Microsoft.Android.Runtime.NativeAotTypeManager::TypeMappings
@@ -77,22 +77,47 @@ protected override void EndProcess ()
77
77
*/
78
78
il . Emit ( Mono . Cecil . Cil . OpCodes . Ldarg_0 ) ;
79
79
il . Emit ( Mono . Cecil . Cil . OpCodes . Ldfld , field ) ;
80
- il . Emit ( Mono . Cecil . Cil . OpCodes . Ldstr , javaKey ) ;
81
- il . Emit ( Mono . Cecil . Cil . OpCodes . Ldtoken , module . ImportReference ( typeDefinition ) ) ;
80
+ il . Emit ( Mono . Cecil . Cil . OpCodes . Ldstr , javaName ) ;
81
+ il . Emit ( Mono . Cecil . Cil . OpCodes . Ldtoken , module . ImportReference ( SelectTypeDefinition ( javaName , list ) ) ) ;
82
82
il . Emit ( Mono . Cecil . Cil . OpCodes . Call , getTypeFromHandle ) ;
83
83
il . Emit ( Mono . Cecil . Cil . OpCodes . Callvirt , addMethod ) ;
84
84
}
85
85
86
86
il . Emit ( Mono . Cecil . Cil . OpCodes . Ret ) ;
87
87
}
88
88
89
+ TypeDefinition SelectTypeDefinition ( string javaName , List < TypeDefinition > list )
90
+ {
91
+ if ( list . Count == 1 )
92
+ return list [ 0 ] ;
93
+
94
+ var best = list [ 0 ] ;
95
+ foreach ( var type in list ) {
96
+ if ( type == best )
97
+ continue ;
98
+ if ( ( type . IsAbstract || type . IsInterface ) &&
99
+ ! best . IsAbstract &&
100
+ ! best . IsInterface &&
101
+ type . IsAssignableFrom ( best , Context ) ) {
102
+ best = type ;
103
+ }
104
+ }
105
+ foreach ( var type in list ) {
106
+ if ( type == best )
107
+ continue ;
108
+ Context . LogMessage ( $ "Duplicate typemap entry for { javaName } => { type . FullName } ") ;
109
+ }
110
+ return best ;
111
+ }
112
+
89
113
void ProcessType ( AssemblyDefinition assembly , TypeDefinition type )
90
114
{
91
115
if ( type . HasJavaPeer ( Context ) ) {
92
116
var javaName = JavaNativeTypeManager . ToJniName ( type , Context ) ;
93
- if ( ! TypeMappings . TryAdd ( javaName , type ) ) {
94
- Context . LogMessage ( $ "Duplicate typemap entry for { javaName } " ) ;
117
+ if ( ! TypeMappings . TryGetValue ( javaName , out var list ) ) {
118
+ TypeMappings . Add ( javaName , list = new List < TypeDefinition > ( ) ) ;
95
119
}
120
+ list . Add ( type ) ;
96
121
}
97
122
98
123
if ( ! type . HasNestedTypes )
0 commit comments