我对一些反射代码感到困惑,并寻找洞察力

Mic*_*yan 6 c# iphone reflection mono unity-game-engine

我正在使用C#和Mono的Full AOT技术为iPhone开发.根据他们的限制页面(链接文本),与传统的Mono/.NET不同,iPhone上的代码是提前静态编译的,而不是由JIT编译器按需编译.

在硬件上运行时,会发生以下异常:

ExecutionEngineException: Attempting to JIT compile method 'System.Reflection.MonoProperty:GetterAdapterFrame<Image, UnityEngine.Color> (System.Reflection.MonoProperty/Getter`2<Image, UnityEngine.Color>,object)' while running with --aot-only. 

System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) [0x00000] 
Ani+AniValue.Get () 
Ani.CreateAnimations (System.Object obj, System.Collections.Hashtable properties, Single duration, System.Collections.Hashtable options, AniType type) 
Ani.Method (AniType type, System.Object obj, Single duration, System.Collections.Hashtable _properties, System.Collections.Hashtable _options) 
Ani.From (System.Object obj, Single duration, System.Collections.Hashtable _properties) 
xObject+<>c__CompilerGenerated5.MoveNext () 
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) 
xObject:StartAnimation(Animate, GameObject, Object, Object) 
SceneSplash:CreateBackground() 
SceneSplash:OnSetup() 
SceneSplash:OnSceneActivate(Callback) 
GameController:ActivateScene() 
GameController:DeactivateScene() 
GameController:SceneLoaded(Scene, GameObject, SceneBase) 
SceneBase:Start()
Run Code Online (Sandbox Code Playgroud)

根据Limitations文档,不支持System.Reflection.Emit,但它们表示作为Reflection.Emit的一面,"整个Reflection API,包括Type.GetType("someClass"),列出方法,列出属性,获取属性和价值观工作得很好."

我已经包含了导致异常的代码......

void CreateAnimations(System.Object obj, Hashtable properties, float duration,
                      Hashtable options, AniType type)
{
    foreach (DictionaryEntry item in properties)
    {
        name = (string)item.Key;                  // Extract name and value
        System.Object value = item.Value;

        AniValue foo = new AniValue(obj, name);   // Create value object

        /* To exception occurs inside Get() */
        System.Object current = foo.Get();        // Get current value

        ...
Run Code Online (Sandbox Code Playgroud)

上面的方法从哈希表中获取属性名称,并使用它(与obj一起)来创建AniValue的实例.之后,调用foo.Get()来检索属性的值.propertyInfo.GetValue(obj,null)发生异常.

using System.Reflection

public class AniValue
{
    static BindingFlags bFlags = BindingFlags.Public | BindingFlags.NonPublic
                                 | BindingFlags.Instance | BindingFlags.Static;

    System.Object obj;  // Object a field or property is animated on
    string name;        // Name of the field or property

    System.Type objType;          // Type object
    FieldInfo fieldInfo;          // FieldInfo object
    PropertyInfo propertyInfo;    // PropertyInfo object

    public AniValue(System.Object o, string n)
    {
        obj = o;
        name = n;
        objType = obj.GetType();
        fieldInfo = objType.GetField(n, AniValue.bFlags);
        propertyInfo = objType.GetProperty(n, AniValue.bFlags);
        if (fieldInfo == null && propertyInfo == null)
        {
            throw new System.MissingMethodException("Property or field '" + n
                                                    + "' not found on " + obj);
        }
    }

    // Get field or property
    public System.Object Get()
    {
        if (propertyInfo != null)
        {
            /* The next line causes the Exception */
            return propertyInfo.GetValue(obj, null);
        }
        else
        {
            return fieldInfo.GetValue(obj);
        }
    }
    ...
Run Code Online (Sandbox Code Playgroud)

虽然我对C#,JIT,AOT和Reflection的经验有限,但是GetValue()会触发JIT吗?UnityEngine.Color是一个结构体,Image类是xObject的子类,它是UnityEngine.MonoBehaviour的子类.Color是Image的一个属性,这就是代码可以获得异常发生时的值.

有趣的是,您可以使用.NET 1.1编译代码,一切正常.只有在使用.NET 2.1进行编译时才会发生异常.

我不知道是否有解决方案或解决这个问题,但我会对任何有关原因的见解感兴趣.

Mar*_*ell 3

IIRC,还有关于通过反射泛型的警告。我相信它调用的是接口而不是具体类型,但这同样适用 - 特别是使用反射时。

就我个人而言,我只是在处理 iPhone 时放弃反思 - 它更容易。我仍在进行元编程,但我正在预先生成常规代码(在完整框架上),然后将其接管到 MonoTouch。它似乎工作得相当稳健。