diff --git a/Directory.Build.props b/Directory.Build.props
index 5da999fb1..c132f796b 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -47,7 +47,7 @@
False
False
- obj\
+ $(MSBuildProjectDirectory)\obj\
diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs
index 1ce3e6543..4102c498e 100644
--- a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs
+++ b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs
@@ -307,7 +307,7 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)
}
targetType = targetType ?? typeof (JavaObject);
- targetType = GetPeerType (targetType);
+ targetType = GetPeerType(targetType);
if (!typeof (IJavaPeerable).IsAssignableFrom (targetType))
throw new ArgumentException ($"targetType `{targetType.AssemblyQualifiedName}` must implement IJavaPeerable!", nameof (targetType));
@@ -359,8 +359,8 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)
if (!JniTypeSignature.TryParse (jniTypeName, out sig))
return null;
- Type? type = GetTypeAssignableTo (sig, targetType);
- if (type != null) {
+ Type? type = GetBestTypeForSignature (sig);
+ if (type != null && type.IsAssignableTo(targetType)) {
var peer = TryCreatePeerInstance (ref reference, transfer, type);
if (peer != null) {
@@ -379,18 +379,57 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)
}
JniObjectReference.Dispose (ref klass, JniObjectReferenceOptions.CopyAndDispose);
+ // If we have nothing in the hierarchy, assume caller knows best and create targetType
return TryCreatePeerInstance (ref reference, transfer, targetType);
+
[UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = "Types returned here should be preserved via other means.")]
[return: DynamicallyAccessedMembers (Constructors)]
- Type? GetTypeAssignableTo (JniTypeSignature sig, Type targetType)
+ Type? GetBestTypeForSignature (JniTypeSignature sig)
{
- foreach (var t in Runtime.TypeManager.GetTypes (sig)) {
- if (targetType.IsAssignableFrom (t)) {
- return t;
+ string[] sdkAssemblyNames = ["Mono.Android", "Java.Base", "Java.Interop"];
+ // Find single best instance
+ Type? best = null;
+ foreach (Type type in Runtime.TypeManager.GetTypes (sig)) {
+ if (best is null) {
+ best = type;
+ continue;
+ }
+ if (type == best)
+ continue;
+ // Types in sdk assemblies should be first in the list
+ if ((uint)Array.IndexOf(sdkAssemblyNames, best.Module.Assembly.GetName ().Name) >
+ (uint)Array.IndexOf(sdkAssemblyNames, type.Module.Assembly.GetName ().Name)) {
+ best = type;
+ continue;
+ }
+ // We found the `Invoker` type *before* the declared type
+ // Fix things up so the abstract type is first, and the `Invoker` is considered a duplicate.
+ if ((type.IsAbstract || type.IsInterface) &&
+ !best.IsAbstract &&
+ !best.IsInterface &&
+ type.IsAssignableFrom (best)) {
+ best = type;
+ continue;
+ }
+
+ // If the type is a derived type of the current best, then it is better
+ if (type.IsAssignableTo(best))
+ {
+ best = type;
+ continue;
+ }
+
+ // we found a generic subclass of a non-generic type
+ if (type.IsGenericType &&
+ !best.IsGenericType &&
+ type.IsAssignableTo (best)) {
+ best = type;
+ continue;
}
}
- return null;
+
+ return best;
}
}
diff --git a/src/java-interop/java-interop.targets b/src/java-interop/java-interop.targets
index 9d35aaa47..fad633f88 100644
--- a/src/java-interop/java-interop.targets
+++ b/src/java-interop/java-interop.targets
@@ -35,13 +35,13 @@
- <_MonoNativePath>$(NuGetPackageRoot)microsoft.netcore.app.runtime.mono.$(NETCoreSdkRuntimeIdentifier)/$(DotNetRuntimePacksVersion)/runtimes/$(NETCoreSdkRuntimeIdentifier)/native/
+ <_MonoNativePath>$(NuGetPackageRoot)\microsoft.netcore.app.runtime.mono.$(NETCoreSdkRuntimeIdentifier)/$(DotNetRuntimePacksVersion)/runtimes/$(NETCoreSdkRuntimeIdentifier)/native/
<_MonoIncludePath>$(_MonoNativePath)include/mono-2.0
<_DEnableMono>-DENABLE_MONO_INTEGRATION=ON
<_DEnableOsxArchitectures Condition=" $([MSBuild]::IsOSPlatform ('osx')) ">"-DENABLE_OSX_ARCHITECTURES=$(_CmakeOsxArch)"
<_DMonoDirs>"-DMONO_INCLUDE_LIST=$(_MonoIncludePath)"
<_DJdkDirs>"-DJDK_INCLUDE_LIST=@(JdkIncludePath, ';')"
- <_DJni_c>"-DJNI_C_PATH=$(MSBuildThisFileDirectory)$(IntermediateOutputPath)jni.c"
+ <_DJni_c>"-DJNI_C_PATH=$(IntermediateOutputPath)jni.c"
<_MonoLinkFlags Condition=" $([MSBuild]::IsOSPlatform ('windows')) " >$(MSBuildThisFileDirectory)coreclr.lib
<_MonoLinkFlags Condition=" !$([MSBuild]::IsOSPlatform ('windows')) ">-L $(_MonoNativePath) -lcoreclr
<_DMonoLinkFlags>"-DMONO_LINK_FLAGS=$(_MonoLinkFlags)"
@@ -71,7 +71,7 @@
<_Cmake Include="CmakePath=$(CmakePath)" />
<_Cmake Include="CmakeGenerator=$(CmakeGenerator)" />
<_Cmake Include="CmakeSourceDir=$(MSBuildThisFileDirectory)" />
- <_Cmake Include="CmakeBuildDir=$(MSBuildThisFileDirectory)$(IntermediateOutputPath)" />
+ <_Cmake Include="CmakeBuildDir=$(IntermediateOutputPath)" />
<_Cmake Include="CmakeExtraArgs=$(_ExtraArgs)" />
-
+ Inputs="$(MSBuildThisFileDirectory)coreclr.def"
+ Outputs="$(MSBuildThisFileDirectory)coreclr.lib">
+
<_Cmake Include="CmakeGenerator=$(CmakeGenerator)" />
<_Cmake Include="CmakeSourceDir=$(MSBuildThisFileDirectory)" />
- <_Cmake Include="CmakeBuildDir=$(MSBuildThisFileDirectory)$(IntermediateOutputPath)%(_NativeTimingLib.Dir)" />
+ <_Cmake Include="CmakeBuildDir=$(IntermediateOutputPath)%(_NativeTimingLib.Dir)" />
<_Cmake Include="CmakeExtraArgs=$(_JdkDirs)" />