Estou confuso sobre alguns códigos de Reflexão, e olhando para a introspecção
-
19-09-2019 - |
Pergunta
Estou desenvolvendo para o iPhone usando C # e tecnologia Full AOT de Mono. De acordo com a sua Limitações página ( link de texto ), ao contrário do tradicional Mono /. NET, o código no iPhone é estaticamente compilado antes do tempo em vez de ser compilado no pedido por um compilador JIT.
Quando executado no hardware, ocorre a seguinte exceção:
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()
De acordo com o documento Limitações, System.Reflection.Emit não é suportado, mas eles afirmam que como o lado de Reflection.Emit, "toda a API Reflection, incluindo Type.GetType (" someClass "), listando métodos, listando propriedades , buscando atributos e valores funciona muito bem. "
Eu incluí o código que está causando a exceção ...
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
...
O método acima agarra um nome de propriedade a partir de uma tabela de dispersão, e usa-o (juntamente com obj) para criar um exemplo de AniValue. Só depois, foo.Get () é chamado para recuperar o valor da propriedade. A exceção ocorre em 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);
}
}
...
Apesar de ter pouca experiência com C #, JIT, AOT, e reflexão, deve GetValue () JIT gatilho? UnityEngine.Color é um struct, ea classe de imagem é como subclasse de XObject, que é uma subclasse de UnityEngine.MonoBehaviour. A cor é uma propriedade de imagem, e é isso que o código poderia estar recebendo o valor de quando ocorre a exceção.
Curiosamente, você pode compilar o código usando .NET 1.1, e tudo executa bem. Somente quando você compilar usando .NET 2.1 ocorre a exceção.
Eu não sei se há uma solução ou contornar a isso, mas eu estaria interessado em qualquer visão sobre a causa.
Solução
IIRC, há também um aviso sobre os genéricos através de reflexão. I acreditam que chama de interfaces em vez de tipos de concreto, mas o mesmo pode ser aplicado -. Em particular, quando usando a reflexão
Pessoalmente, eu só estou caindo reflexão quando se lida com iPhone - é mais fácil. Eu ainda estou fazendo meta-programação, mas eu sou pré-gerar o código normal (sobre o quadro completo) que eu, em seguida, assumir a MonoTouch. Parece funcionar muito robusta.