我对一些反射代码感到困惑,并寻找洞察力
Posted
技术标签:
【中文标题】我对一些反射代码感到困惑,并寻找洞察力【英文标题】:I'm confused about some Reflection code, and looking for insight 【发布时间】:2011-01-26 08:08:27 【问题描述】:我正在使用 C# 和 Mono 的 Full AOT 技术为 iPhone 进行开发。根据他们的限制页面 (link text),与传统的 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()
根据限制文档,不支持 System.Reflection.Emit,但他们声明作为 Reflection.Emit 的一面,“整个反射 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
...
上述方法从哈希表中获取属性名称,并使用它(与 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);
...
虽然我在 C#、JIT、AOT 和反射方面的经验有限,但 GetValue() 是否应该触发 JIT? UnityEngine.Color 是一个结构体,Image 类是 xObject 的子类,xObject 是 UnityEngine.MonoBehaviour 的子类。颜色是 Image 的一个属性,当异常发生时,这就是代码可能获取的值。
有趣的是,您可以使用 .NET 1.1 编译代码,并且一切正常。只有当您使用 .NET 2.1 进行编译时才会发生异常。
我不知道是否有解决方案或解决此问题的方法,但我有兴趣了解有关原因的任何见解。
【问题讨论】:
这似乎不是 S.R.E.,它可能是 MonoTouch 本身的一个错误,您应该联系他们或 Unity。 我向 Unity 团队提交了一份错误报告,以防万一是错误。 【参考方案1】:IIRC,还有一个关于泛型通过反射的警告。我相信它调用的是接口而不是具体的类型,但同样的情况也可能适用——在使用反射时特别是。
就个人而言,我只是在处理 iPhone 时放弃反射 - 它更容易。我仍在进行元编程,但我正在预生成常规代码(在完整框架上),然后我将其接管给 MonoTouch。它似乎工作得相当稳健。
【讨论】:
此时项目代码中的任何地方都没有使用泛型,否则我不希望它会在 .NET 1.1 下运行,但确实如此。此外,当我手动解决问题 GetValue() 调用时,应用程序的其余部分运行良好,即使后来有对同一属性的反射 SetValue() 调用并且这些调用没有问题。上面链接的限制文档让我相信这应该有效,因为它明确指出,“列出方法、列出属性、获取属性和值工作得很好”。我想我会采纳你的建议并远离反射。 @Michael -GetterAdapterFrame<Image, UnityEngine.Color>
对我来说看起来很普通
确实如此。我的意思是说 my 代码中没有使用泛型。我猜测 PropertyInfo.GetValue() 方法在 Mono/.NET 2.1 框架内部使用泛型,这导致了异常。谢谢!以上是关于我对一些反射代码感到困惑,并寻找洞察力的主要内容,如果未能解决你的问题,请参考以下文章