c# - 在 iOS 上的 C# IL2CPP 中通过反射调用泛型方法

标签 c# ios unity-game-engine reflection il2cpp

这个问题专门针对 Unity3d IL2CPP 和 iOS。

使用反射调用泛型方法

class SourceValue<T> { public T value; }
class TargetValue<T> { public T value; }

static TargetValue<T> GenericMethod<T> (SourceValue<T> source) {
    return new TargetValue<T> { value = source.value };
}

void Main () {
    Type genericType = typeof(SourceValue<float>);
    Type typeArg = genericType.GenericTypeArguments[0];
    MethodInfo mi = GetType ().GetMethod ("GenericMethod", Flags | BindingFlags.Static);
    MethodInfo gmi = mi.MakeGenericMethod (typeArg);
    object src = new SourceValue<float> { value = 0.5f };
    object trg = gmi.Invoke (this, new object[] { src });
}

这在 Mac 上的 Unity 编辑器中运行时按预期工作。在 iOS 上调用失败并出现错误:

ExecutionEngineException: Attempting to call method 'GenericMethod<System.Single>' for which no ahead of time (AOT) code was generated.
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0  

仅仅是 AOT 系统不能调用泛型方法还是我遗漏了什么?

最佳答案

是的,因为 IL2CPP 是一个提前 (AOT) 编译器,它只适用于编译时存在的代码。这里没有代码使用 GenericMethod<float>在“真正的”C# 源代码中,因此 IL2CPP 不知道生成相应的代码来使该实现工作。

这里真正的限制是泛型参数类型是 float ,这是一个值类型。你可以使用 string (引用类型)在这种情况下没有任何问题。 IL2CPP 共享所有具有引用类型的泛型参数的泛型类型的实现(例如 stringobject 等)。这是可能的,因为 C# 中的所有引用类型都具有相同的大小(准确地说是 IntrPtr.Size)。

所以这里的限制实际上是双重的:

  1. IL2CPP 只能生成编译时已知的代码
  2. 当类型参数是值类型时,此限制仅适用于泛型。

请注意,理论上 IL2CPP 也可以共享具有值类型泛型参数的泛型类型的实现,尽管尚未实现。

编辑:从 Unity 2022.2 开始,这已经实现 - ExecutionEngineException不会再发生,原来的场景会起作用。

关于c# - 在 iOS 上的 C# IL2CPP 中通过反射调用泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56183606/

相关文章:

c# - 匹配所有有效格式 IPv6 地址的正则表达式

ios - 单击时从一个标签栏移动到另一个标签栏(带有导航 Controller 的标签栏)

iphone - 如何在 OpenGL ES 2.0 中为每个网格加载不同的纹理?

ios - RootViewController 上的 NSInternalInconsistencyException

ios - Unity3d iOS 构建 exportArchive IPA 大小

unity-game-engine - Unity UNET - 在玩家对象之外调用 [Command]

c# - 通过电子邮件链接验证用户帐户

c# - 两个表的 Fluent Nhibernate 映射一对多在映射中使用唯一而不是主键

c# - 3 尝试使用 C# 删除 XML 节点

c# - 不能同时旋​​转和移动