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)); } }
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(); } }
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)); } }
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); } }
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)); } }
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)); }
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); }