internal static IJavaObject JavaCast(IJavaObject instance, Type resultType)
        {
            if (resultType == null)
            {
                throw new ArgumentNullException("resultType");
            }

            if (instance == null)
            {
                return(null);
            }

            if (resultType.IsAssignableFrom(instance.GetType()))
            {
                return(instance);
            }

            if (resultType.IsClass)
            {
                return(CastClass(instance, resultType));
            }
            else if (resultType.IsInterface)
            {
                return(Java.Lang.Object.GetObject(instance.Handle, JniHandleOwnership.DoNotTransfer, resultType));
            }
            else
            {
                throw new NotSupportedException(string.Format("Unable to convert type '{0}' to '{1}'.",
                                                              instance.GetType().FullName, resultType.FullName));
            }
        }
        static IJavaObject CastClass(IJavaObject instance, Type resultType)
        {
            var klass = JNIEnv.FindClass(resultType);

            try {
                if (klass == IntPtr.Zero)
                {
                    throw new ArgumentException("Unable to determine JNI class for '" + resultType.FullName + "'.", "TResult");
                }
                if (!JNIEnv.IsInstanceOf(instance.Handle, klass))
                {
                    throw new InvalidCastException(
                              string.Format("Unable to convert instance of type '{0}' to type '{1}'.",
                                            instance.GetType().FullName, resultType.FullName));
                }
            } finally {
                JNIEnv.DeleteGlobalRef(klass);
            }

            if (resultType.IsAbstract)
            {
                // TODO: keep in sync with TypeManager.CreateInstance() algorithm
                Type invokerType = GetHelperType(resultType, "Invoker");
                if (invokerType == null)
                {
                    throw new ArgumentException("Unable to get Invoker for abstract type '" + resultType.FullName + "'.", "TResult");
                }
                resultType = invokerType;
            }
            return((IJavaObject)TypeManager.CreateProxy(resultType, instance.Handle, JniHandleOwnership.DoNotTransfer));
        }
        internal static TResult _JavaCast <TResult> (this IJavaObject instance)
        {
            if (instance == null)
            {
                return(default(TResult));
            }

            if (instance is TResult)
            {
                return((TResult)instance);
            }

            Type resultType = typeof(TResult);

            if (resultType.IsClass)
            {
                return((TResult)CastClass(instance, resultType));
            }
            else if (resultType.IsInterface)
            {
                return((TResult)Java.Lang.Object.GetObject(instance.Handle, JniHandleOwnership.DoNotTransfer, resultType));
            }
            else
            {
                throw new NotSupportedException(string.Format("Unable to convert type '{0}' to '{1}'.",
                                                              instance.GetType().FullName, resultType.FullName));
            }
        }
예제 #4
0
        private static void TryDispose(this IJavaObject javaObject)
        {
            if (!javaObject.IsAlive())
            {
                return;
            }
            var hasDefaultConstructor = ObjectToDefaultJavaConstructor
                                        .GetOrAdd(javaObject.GetType(), type =>
            {
                var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, DefaultJavaConstructorArgs, null);
                if (constructor == null)
                {
                    if (Tracer.TraceWarning)
                    {
                        Tracer.Warn($"The type {type} cannot be disposed");
                    }
                    return(false);
                }
                return(true);
            });

            if (hasDefaultConstructor)
            {
                javaObject.Dispose();
            }
        }
예제 #5
0
        internal static TResult _JavaCast <TResult> (this IJavaObject instance)
        {
            if (instance == null)
            {
                return(default(TResult));
            }

            if (instance is TResult)
            {
                return((TResult)instance);
            }

            Type resultType = typeof(TResult);

            if (resultType.IsClass)
            {
                return((TResult)CastClass(instance, resultType));
            }
            else if (resultType.IsInterface)
            {
                Type invokerType = GetHelperType(resultType, "Invoker");
                if (invokerType == null)
                {
                    throw new ArgumentException("Unable to get Invoker for interface '" + resultType.FullName + "'.", "TResult");
                }
                Func <IntPtr, JniHandleOwnership, TResult> getObject = (Func <IntPtr, JniHandleOwnership, TResult>)Delegate.CreateDelegate(typeof(Func <IntPtr, JniHandleOwnership, TResult>), invokerType, "GetObject");
                return(getObject(instance.Handle, JniHandleOwnership.DoNotTransfer));
            }
            else
            {
                throw new NotSupportedException(string.Format("Unable to convert type '{0}' to '{1}'.",
                                                              instance.GetType().FullName, resultType.FullName));
            }
        }
예제 #6
0
        internal static void RegisterInstance(IJavaObject instance, IntPtr value, JniHandleOwnership transfer, out IntPtr handle)
        {
            if (value == IntPtr.Zero)
            {
                handle = value;
                return;
            }

            var transferType = transfer & (JniHandleOwnership.DoNotTransfer | JniHandleOwnership.TransferLocalRef | JniHandleOwnership.TransferGlobalRef);

            switch (transferType)
            {
            case JniHandleOwnership.DoNotTransfer:
                handle = JNIEnv.NewGlobalRef(value);
                break;

            case JniHandleOwnership.TransferLocalRef:
                handle = JNIEnv.NewGlobalRef(value);
                JNIEnv.DeleteLocalRef(value);
                break;

            case JniHandleOwnership.TransferGlobalRef:
                handle = value;
                break;

            default:
                throw new ArgumentOutOfRangeException("transfer", transfer,
                                                      "Invalid `transfer` value: " + transfer + " on type " + instance.GetType());
            }
            if (handle == IntPtr.Zero)
            {
                throw new InvalidOperationException("Unable to allocate Global Reference for object '" + instance.ToString() + "'!");
            }

            IntPtr key = JNIEnv.IdentityHash(handle);

            if ((transfer & JniHandleOwnership.DoNotRegister) == 0)
            {
                _RegisterInstance(instance, key, handle);
            }
            var ex = instance as IJavaObjectEx;

            if (ex != null)
            {
                ex.KeyHandle = key;
            }

            if (Logger.LogGlobalRef)
            {
                JNIEnv._monodroid_gref_log("handle 0x" + handle.ToString("x") +
                                           "; key_handle 0x" + key.ToString("x") +
                                           ": Java Type: `" + JNIEnv.GetClassNameFromInstance(handle) + "`; " +
                                           "MCW type: `" + instance.GetType().FullName + "`\n");
            }
        }
 /// <summary>
 /// 将 <see cref="IJavaObject"/> 转换为泛型类型,常用于修复绑定库中泛型丢失导致的问题
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="obj"></param>
 /// <returns></returns>
 public static T Cast <T>(this IJavaObject obj)
 {
     if (obj is T t)
     {
         return(t);
     }
     else
     {
         var msg = $"Java generic binding conversion failed, obj_type: {obj?.GetType()}, t_type: {typeof(T)}.";
         throw new InvalidCastException(msg);
     }
 }
예제 #8
0
        internal static IJavaObject JavaCast(IJavaObject instance, Type resultType)
        {
            if (resultType == null)
            {
                throw new ArgumentNullException("resultType");
            }

            if (instance == null)
            {
                return(null);
            }

            if (resultType.IsAssignableFrom(instance.GetType()))
            {
                return(instance);
            }

            if (resultType.IsClass)
            {
                return(CastClass(instance, resultType));
            }
            else if (resultType.IsInterface)
            {
                Type invokerType = GetHelperType(resultType, "Invoker");
                if (invokerType == null)
                {
                    throw new ArgumentException("Unable to get Invoker for interface '" + resultType.FullName + "'.", "resultType");
                }
                var getObject = invokerType.GetMethod("GetObject", new[] { typeof(IntPtr), typeof(JniHandleOwnership) });
                return((IJavaObject)getObject.Invoke(null, new object[] { instance.Handle, JniHandleOwnership.DoNotTransfer }));
            }
            else
            {
                throw new NotSupportedException(string.Format("Unable to convert type '{0}' to '{1}'.",
                                                              instance.GetType().FullName, resultType.FullName));
            }
        }
예제 #9
0
        public static object FromJavaObject(IJavaObject value, Type targetType = null)
        {
            if (value == null)
            {
                return(null);
            }

            if (targetType != null && typeof(IJavaObject).IsAssignableFrom(targetType))
            {
                return(JavaObjectExtensions.JavaCast(value, targetType));
            }

            var o = value as JavaObject;

            if (o != null)
            {
                if (targetType == null)
                {
                    return(o.Instance);
                }
                return(Convert.ChangeType(o.Instance, targetType));
            }

            if (targetType == null || targetType.IsAssignableFrom(value.GetType()))
            {
                return(value);
            }

            IntPtr lrefValue = JNIEnv.ToLocalJniHandle(value);

            if (lrefValue == IntPtr.Zero)
            {
                return(null);
            }
            Func <IntPtr, JniHandleOwnership, object> converter = GetJniHandleConverter(targetType);

            if (converter != null)
            {
                return(converter(lrefValue, JniHandleOwnership.TransferLocalRef));
            }
            JNIEnv.DeleteLocalRef(lrefValue);
            return(Convert.ChangeType(value, targetType));
        }
예제 #10
0
        internal static IJavaObject PeekObject(IntPtr handle, Type requiredType = null)
        {
            if (handle == IntPtr.Zero)
            {
                return(null);
            }

            lock (instances) {
                List <WeakReference> wrefs;
                if (instances.TryGetValue(JNIEnv.IdentityHash(handle), out wrefs))
                {
                    for (int i = 0; i < wrefs.Count; ++i)
                    {
                        var         wref = wrefs [i];
                        IJavaObject res  = wref.Target as IJavaObject;
                        if (res != null && res.Handle != IntPtr.Zero && JNIEnv.IsSameObject(handle, res.Handle))
                        {
                            if (requiredType != null && !requiredType.IsAssignableFrom(res.GetType()))
                            {
                                return(null);
                            }
                            return(res);
                        }
                    }
                }
            }
            return(null);
        }