Skip to content
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<!-- Workaround: https://github.com/dotnet/runtime/issues/55992 -->
<UseAppHost>False</UseAppHost>
<AppendTargetFrameworkToOutputPath Condition=" '$(AppendTargetFrameworkToOutputPath)' == '' ">False</AppendTargetFrameworkToOutputPath>
<BaseIntermediateOutputPath Condition=" '$(BaseIntermediateOutputPath)' == '' ">obj\</BaseIntermediateOutputPath>
<BaseIntermediateOutputPath Condition=" '$(BaseIntermediateOutputPath)' == '' ">$(MSBuildProjectDirectory)\obj\</BaseIntermediateOutputPath>
</PropertyGroup>

<PropertyGroup>
Expand Down
55 changes: 47 additions & 8 deletions src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/java-interop/java-interop.targets
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
</PropertyGroup>

<PropertyGroup>
<_MonoNativePath>$(NuGetPackageRoot)microsoft.netcore.app.runtime.mono.$(NETCoreSdkRuntimeIdentifier)/$(DotNetRuntimePacksVersion)/runtimes/$(NETCoreSdkRuntimeIdentifier)/native/</_MonoNativePath>
<_MonoNativePath>$(NuGetPackageRoot)\microsoft.netcore.app.runtime.mono.$(NETCoreSdkRuntimeIdentifier)/$(DotNetRuntimePacksVersion)/runtimes/$(NETCoreSdkRuntimeIdentifier)/native/</_MonoNativePath>
<_MonoIncludePath>$(_MonoNativePath)include/mono-2.0</_MonoIncludePath>
<_DEnableMono>-DENABLE_MONO_INTEGRATION=ON</_DEnableMono>
<_DEnableOsxArchitectures Condition=" $([MSBuild]::IsOSPlatform ('osx')) ">"-DENABLE_OSX_ARCHITECTURES=$(_CmakeOsxArch)"</_DEnableOsxArchitectures>
<_DMonoDirs>"-DMONO_INCLUDE_LIST=$(_MonoIncludePath)"</_DMonoDirs>
<_DJdkDirs>"-DJDK_INCLUDE_LIST=@(JdkIncludePath, ';')"</_DJdkDirs>
<_DJni_c>"-DJNI_C_PATH=$(MSBuildThisFileDirectory)$(IntermediateOutputPath)jni.c"</_DJni_c>
<_DJni_c>"-DJNI_C_PATH=$(IntermediateOutputPath)jni.c"</_DJni_c>
<_MonoLinkFlags Condition=" $([MSBuild]::IsOSPlatform ('windows')) " >$(MSBuildThisFileDirectory)coreclr.lib</_MonoLinkFlags>
<_MonoLinkFlags Condition=" !$([MSBuild]::IsOSPlatform ('windows')) ">-L $(_MonoNativePath) -lcoreclr</_MonoLinkFlags>
<_DMonoLinkFlags>"-DMONO_LINK_FLAGS=$(_MonoLinkFlags)"</_DMonoLinkFlags>
Expand Down Expand Up @@ -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)" />
</ItemGroup>
<MSBuild
Expand All @@ -86,9 +86,9 @@

<Target Name="_UpdateCoreCLRLib"
Condition=" $([MSBuild]::IsOSPlatform ('windows')) And '$(NativeToolchainSupported)' == 'True' "
Inputs="coreclr.def"
Outputs="corclr.lib">
<Exec Command="lib /def:coreclr.def /out:coreclr.lib /machine:X64" />
Inputs="$(MSBuildThisFileDirectory)coreclr.def"
Outputs="$(MSBuildThisFileDirectory)coreclr.lib">
<Exec Command="lib /def:$(MSBuildThisFileDirectory)coreclr.def /out:$(MSBuildThisFileDirectory)coreclr.lib /machine:X64" />
</Target>

<Target Name="_Clean"
Expand Down
2 changes: 1 addition & 1 deletion tests/NativeTiming/NativeTiming.targets
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<_Cmake Include="CmakePath=$(CmakePath)" />
<_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)" />
</ItemGroup>
<MSBuild
Expand Down