Skip to content

[Mono.Android] Java.Lang.Object.GetObject<T>() implementation #9728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/Mono.Android/Android.App/Activity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace Android.App {

partial class Activity {

internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

public T? FindViewById<
[DynamicallyAccessedMembers (Constructors)]
T
Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.App/Dialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ protected Dialog (Android.Content.Context context, bool cancelable, EventHandler
: this (context, cancelable, new Android.Content.IDialogInterfaceOnCancelListenerImplementor () { Handler = cancelHandler }) {}

public T? FindViewById<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[DynamicallyAccessedMembers (Constructors)]
T
> (int id)
where T : Android.Views.View
Expand Down
2 changes: 0 additions & 2 deletions src/Mono.Android/Android.App/FragmentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#if ANDROID_11
namespace Android.App {
public partial class FragmentManager {
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

public T? FindFragmentById<
[DynamicallyAccessedMembers (Constructors)]
T
Expand Down
2 changes: 0 additions & 2 deletions src/Mono.Android/Android.OS/AsyncTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ public abstract class AsyncTask<
TResult
> : AsyncTask {

const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

static IntPtr java_class_handle;
internal static IntPtr class_ref {
get {
Expand Down
8 changes: 7 additions & 1 deletion src/Mono.Android/Android.Runtime/JNIEnv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,13 @@ public static void CopyArray (IntPtr src, string[] dest)
AssertIsJavaObject (type);

IntPtr elem = GetObjectArrayElement (source, index);
return Java.Lang.Object.GetObject (elem, JniHandleOwnership.TransferLocalRef, type);
return GetObject (elem, type);

// FIXME: Since a Dictionary<Type, Func> is used here, the trimmer will not be able to properly analyze `Type t`
// error IL2111: Method 'lambda expression' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
[UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = "FIXME: https://github.com/xamarin/xamarin-android/issues/8724")]
static object? GetObject (IntPtr e, Type t) =>
Java.Lang.Object.GetObject (e, JniHandleOwnership.TransferLocalRef, t);
} },
{ typeof (Array), (type, source, index) => {
IntPtr elem = GetObjectArrayElement (source, index);
Expand Down
7 changes: 5 additions & 2 deletions src/Mono.Android/Android.Runtime/JavaArray.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System;
using System.Collections;
using System.Collections.Generic;

using System.Diagnostics.CodeAnalysis;

namespace Android.Runtime {

[Register ("mono/android/runtime/JavaArray", DoNotGenerateAcw=true)]
public sealed class JavaArray<T> : Java.Lang.Object, IList<T> {
public sealed class JavaArray<
[DynamicallyAccessedMembers (Constructors)]
T
> : Java.Lang.Object, IList<T> {

public JavaArray (IntPtr handle, JniHandleOwnership transfer)
: base (handle, transfer)
Expand Down
2 changes: 0 additions & 2 deletions src/Mono.Android/Android.Runtime/JavaCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ namespace Android.Runtime {
// java.util.Collection allows null values
public class JavaCollection : Java.Lang.Object, System.Collections.ICollection {

internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

internal static IntPtr collection_class = JNIEnv.FindClass ("java/util/Collection");

internal static IntPtr id_add;
Expand Down
2 changes: 0 additions & 2 deletions src/Mono.Android/Android.Runtime/JavaDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ namespace Android.Runtime {
// java.util.HashMap allows null keys and values
public class JavaDictionary : Java.Lang.Object, System.Collections.IDictionary {

internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

class DictionaryEnumerator : IDictionaryEnumerator {

IEnumerator simple_enumerator;
Expand Down
1 change: 0 additions & 1 deletion src/Mono.Android/Android.Runtime/JavaList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace Android.Runtime {
// java.util.ArrayList allows null values
public partial class JavaList : Java.Lang.Object, System.Collections.IList {

internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
internal static readonly JniPeerMembers list_members = new XAPeerMembers ("java/util/List", typeof (JavaList), isInterface: true);

//
Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.Runtime/JavaSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ public static IntPtr ToLocalJniHandle (ICollection? items)
[Register ("java/util/HashSet", DoNotGenerateAcw=true)]
// java.util.HashSet allows null
public class JavaSet<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[DynamicallyAccessedMembers (Constructors)]
T
> : JavaSet, ICollection<T> {

Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.Util/SparseArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Android.Util
{
[Register ("android/util/SparseArray", DoNotGenerateAcw=true)]
public partial class SparseArray<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[DynamicallyAccessedMembers (Constructors)]
E
> : SparseArray
{
Expand Down
3 changes: 0 additions & 3 deletions src/Mono.Android/Android.Views/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ public enum SystemUiFlags {
#endif

public partial class View {

internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

#if ANDROID_16
[Obsolete ("This method uses wrong enum type. Please use PerformAccessibilityAction(Action) instead.")]
public bool PerformAccessibilityAction (GlobalAction action, Bundle arguments)
Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.Views/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Android.Views {
partial class Window {

public T? FindViewById<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[DynamicallyAccessedMembers (Constructors)]
T
> (int id)
where T : Android.Views.View
Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.Widget/AdapterView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public event EventHandler ItemSelectionCleared {

[Register ("android/widget/AdapterView", DoNotGenerateAcw=true)]
public abstract class AdapterView<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[DynamicallyAccessedMembers (Constructors)]
T
> : AdapterView where T : IAdapter {

Expand Down
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.Widget/ArrayAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Android.Widget {

[Register ("android/widget/ArrayAdapter", DoNotGenerateAcw=true)]
public partial class ArrayAdapter<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[DynamicallyAccessedMembers (Constructors)]
T
> : ArrayAdapter {

Expand Down
33 changes: 22 additions & 11 deletions src/Mono.Android/Java.Lang/Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace Java.Lang {
[Serializable]
public partial class Object : global::Java.Interop.JavaObject, IJavaObject, IJavaObjectEx
{
internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;

IntPtr IJavaObjectEx.ToLocalJniHandle ()
{
lock (this) {
Expand Down Expand Up @@ -130,39 +132,48 @@ protected void SetHandle (IntPtr value, JniHandleOwnership transfer)
return (T?)PeekObject (handle, typeof (T));
}

public static T? GetObject<T> (IntPtr jnienv, IntPtr handle, JniHandleOwnership transfer)
public static T? GetObject<
[DynamicallyAccessedMembers (Constructors)]
T
> (IntPtr jnienv, IntPtr handle, JniHandleOwnership transfer)
where T : class, IJavaObject
{
JNIEnv.CheckHandle (jnienv);
return GetObject<T> (handle, transfer);
}

public static T? GetObject<T> (IntPtr handle, JniHandleOwnership transfer)
public static T? GetObject<
[DynamicallyAccessedMembers (Constructors)]
T
> (IntPtr handle, JniHandleOwnership transfer)
where T : class, IJavaObject
{
return _GetObject<T>(handle, transfer);
}

internal static T? _GetObject<T> (IntPtr handle, JniHandleOwnership transfer)
internal static T? _GetObject<
[DynamicallyAccessedMembers (Constructors)]
T
> (IntPtr handle, JniHandleOwnership transfer)
{
if (handle == IntPtr.Zero)
return default (T);

return (T?) GetObject (handle, transfer, typeof (T));
}

internal static IJavaPeerable? GetObject (IntPtr handle, JniHandleOwnership transfer, Type? type = null)
internal static IJavaPeerable? GetObject (
IntPtr handle,
JniHandleOwnership transfer,
[DynamicallyAccessedMembers (Constructors)]
Type? type = null)
{
if (handle == IntPtr.Zero)
return null;

var r = PeekObject (handle, type);
if (r != null) {
JNIEnv.DeleteRef (handle, transfer);
return r;
}

return Java.Interop.TypeManager.CreateInstance (handle, transfer, type);
var r = JNIEnvInit.ValueManager!.GetPeer (new JniObjectReference (handle), type);
JNIEnv.DeleteRef (handle, transfer);
return r;
}

[EditorBrowsable (EditorBrowsableState.Never)]
Expand Down