android 如何从Java.Lang.Class示例或JNI类型中获取.NET类型?

7gs2gvoe  于 2022-12-09  发布在  Android
关注(0)|答案(2)|浏览(123)

我正在使用Xamarin.Android,我正在尝试扩展默认FragmentFactory的功能。

public class ExtendedFragmentFactory : FragmentFactory
{
    public override Fragment Instantiate(ClassLoader classLoader, string className)
    {
        Class javaClass = Class.ForName(className, false, classLoader);
        var instance = javaClass.NewInstance();
    }
}

如果我使用NewInstance()创建一个新的示例,那么我就可以在instance上调用GetType(),这确实会给予我.NET类型,但是我该如何在不创建不必要的示例的情况下完成这一操作呢?
我正在尝试使用依赖容器创建Fragment,因此无法使用Android用于FragmentManagerFragmentFactory的默认示例化方法。我的Fragment类将通过其构造函数将依赖项注入其中,换句话说,我将无法使用默认示例化实现所需的无参数构造函数。
有没有办法从Java.Lang.Class或Instantiate方法中的指定参数获取.NET类型?
是否有任何方法可以使用className参数来确定.NET类型是什么?

gzszwxb4

gzszwxb41#

使用TypeManager,我设法从className参数获得了.NET托管类型。

Type type = JniEnvironment.Runtime.TypeManager.GetType(JniTypeSignature.Parse($"[L{className.Replace('.', '/')};"))!;
if (type.IsGenericType)
{
    type = type.GetGenericArguments().First();
}

需要将className值“转换”为有效的JNI签名,这相对来说比较简单,只需要对JNI有一个基本的了解。
返回的值属于Java.Interop.JavaObjectArray<T>类型,因此调用GetGenericArguments()将获得正确的.NET托管类型。
通过使用"RegisterAttribute“,我能够找到一种方法来确保”className“具有.NET类型的完全限定名。

[Register("Namespace.SomeFragment")
public class SomeFragment : Fragment
{
}

这是一个有点乏味的过程,特别是如果你有很多Fragment类(像我一样)。

kxe2p93d

kxe2p93d2#

默认情况下,Java.Lang.Class具有GetType()方法:

Class javaClass = Class.ForName(className, false, classLoader);
var dotNetType = javaClass.GetType();

相关问题