如何在Xamarin.Android绑定项目中使用Kotlin.Result?
解决Xamarin.Android中Kotlin.Result的取值与泛型问题
核心问题分析
你遇到的是Xamarin.Kotlin.StdLib绑定不完整导致的问题:1.7.20.1版本缺失Kotlin.Result的泛型实现与核心方法(如getOrThrow、getOrNull),旧版本的ThrowIfFailure也已移除,靠ToString解析的方法仅适用于简单类型,对复杂类完全无效。
可行解决方案
1. 反射调用Kotlin.Result的原生方法
Kotlin.Result在JVM编译后其实保留了isSuccess()、isFailure()、getOrNull()、exceptionOrNull()这些核心方法,只是Xamarin绑定未生成对应的C#封装。你可以通过反射直接调用这些方法:
using System.Reflection; public static T GetResultValue<T>(object resultInstance) { Type resultType = resultInstance.GetType(); // 判断是否为成功结果 MethodInfo isSuccessMethod = resultType.GetMethod("isSuccess"); bool isSuccess = (bool)isSuccessMethod.Invoke(resultInstance, null); if (isSuccess) { // 获取成功值 MethodInfo getOrNullMethod = resultType.GetMethod("getOrNull"); return (T)getOrNullMethod.Invoke(resultInstance, null); } else { // 获取失败异常并抛出 MethodInfo exceptionOrNullMethod = resultType.GetMethod("exceptionOrNull"); Exception ex = (Exception)exceptionOrNullMethod.Invoke(resultInstance, null); throw ex ?? new InvalidOperationException("Result failed with no exception"); } }
使用示例:
// 假设yourResult是从绑定库获取的Result<SomeClass>实例 SomeClass value = GetResultValue<SomeClass>(yourResult);
2. 调整Xamarin绑定元数据(Metadata.xml)
如果能修改绑定项目的元数据,可以手动添加Result类的方法绑定,让Xamarin生成对应的C#封装:
在绑定项目的Metadata.xml中添加以下内容(根据反编译aar中Result的实际方法签名调整):
<attr path="/api/package[@name='kotlin']/class[@name='Result']" name="visibility">public</attr> <attr path="/api/package[@name='kotlin']/class[@name='Result']/method[@name='getOrNull']" name="managedName">GetOrNull</attr> <attr path="/api/package[@name='kotlin']/class[@name='Result']/method[@name='isSuccess']" name="managedName">IsSuccess</attr> <attr path="/api/package[@name='kotlin']/class[@name='Result']/method[@name='exceptionOrNull']" name="managedName">ExceptionOrNull</attr>
添加后重新生成绑定项目,就能直接调用这些方法,无需反射。
3. 获取Result的泛型类型
要获取Result的泛型参数类型,同样可以通过反射实现:
public static Type GetResultGenericType(object resultInstance) { Type resultType = resultInstance.GetType(); // 若绑定后的Result是泛型类型,直接取泛型参数 if (resultType.IsGenericType) { return resultType.GetGenericArguments()[0]; } // 若为非泛型绑定,通过获取值的类型间接判断 MethodInfo getOrNullMethod = resultType.GetMethod("getOrNull"); object value = getOrNullMethod.Invoke(resultInstance, null); return value?.GetType(); }
4. 备选方案:Kotlin端封装(若可修改原包)
如果能控制原Kotlin库的代码,可以在Kotlin端封装一层,将Result的结果拆分为更易被Xamarin处理的形式,比如:
// 直接返回Nullable类型 fun yourOriginalFunction(): String? { return runCatching { originalResultReturningFunction() }.getOrNull() } // 或者返回结果与异常的Pair fun yourOriginalFunction(): Pair<String?, Throwable?> { val result = originalResultReturningFunction() return Pair(result.getOrNull(), result.exceptionOrNull()) }
内容的提问来源于stack exchange,提问作者albertb22
相关产品推荐
相关产品推荐

