API basada en la reflexión

En algunos casos, el uso de la reflexión en el código no es obvio y, por tanto, la cadena de herramientas .NET Native no conserva los metadatos necesarios en tiempo de ejecución. En este tema se abordan algunas de las API comunes o patrones de programación habituales que no se consideran parte de la API de reflexión, pero que hacen uso de la reflexión para ejecutarse correctamente. Si los usa en su código fuente, puede agregar información sobre ellos en el archivo de directivas en tiempo de ejecución (.rd.xml) para que las llamadas a estas API no generen una excepción MissingMetadataException u otra excepción en tiempo de ejecución.

Método Type.MakeGenericType

Puede crear dinámicamente instancias de un tipo genérico AppClass<T> llamando al método Type.MakeGenericType mediante código como el siguiente:

var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);

Para que este código se ejecute correctamente en tiempo de ejecución, son necesarios varios elementos de metadatos. El primero son metadatos de Browse para el tipo genérico sin instancia, AppClass<T>:

<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />

Esto permite que la llamada al método Type.GetType(String, Boolean) se realice correctamente y devuelva un objeto Type válido.

Sin embargo, aun cuando se agreguen metadatos para el tipo genérico sin instancia, la llamada al método Type.MakeGenericType genera una excepción MissingMetadataException:

Esta operación no se puede llevar a cabo como metadatos para el siguiente tipo se quitó por motivos de rendimiento:

App1.AppClass`1<System.Int32>.

Puede incluir la siguiente directiva en tiempo de ejecución al archivo de directivas en tiempo de ejecución para agregar metadatos de Activate para la creación específica de instancias sobre AppClass<T> de System.Int32:

<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
                   Activate="Required Public" />

Cada instancia AppClass<T> diferente requiere una directiva independiente si se crea con el Type.MakeGenericType método y no se usa estáticamente.

Método MethodInfo.MakeGenericMethod

Dada una clase Class1 con un método genérico GetMethod<T>(T t), se puede invocar a GetMethod mediante reflexión con código como el siguiente:

Type ct = typeof(Class1);
MethodInfo mi = ct.GetMethod("GetMethod");
Type[] typeArgs = {typeof(int)};
object[] parameters = { 12 };
var method = mi.MakeGenericMethod(typeArgs);
Class1 c = new Class1();
method.Invoke(c, parameters);

Para ejecutarse correctamente, este código requiere varios elementos de metadatos:

  • Metadatos de Browse para el tipo cuyo método se quiere llamar.

  • Metadatos de Browse para el método que se quiere llamar. Si se trata de un método público, la adición de metadatos de Browse públicos para el tipo contenedor incluye también el método.

  • Metadatos dinámicos para el método al que desea llamar, de modo que la cadena de herramientas .NET Native no quite el delegado de invocación de reflexión. Si no hay metadatos dinámicos para el método, se generará la siguiente excepción cuando se llame al método MethodInfo.MakeGenericMethod:

    MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
    

Las siguientes directivas en tiempo de ejecución procuran que estén disponibles todos los metadatos necesarios:

<Type Name="App1.Class1" Browse="Required PublicAndInternal">
   <MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>

Se necesita una directiva MethodInstantiation por cada creación de instancia diferente del método que se invoca dinámicamente, y el elemento Arguments se actualiza para reflejar cada argumento de creación de instancia diferente.

Métodos Array.CreateInstance y Type.MakeTypeArray

En el siguiente ejemplo se llama a los métodos Type.MakeArrayType y Array.CreateInstance en un tipo, Class1.

Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);

Si no hay metadatos de matriz presentes, se produce el siguiente error:

This operation cannot be carried out as metadata for the following type was removed for performance reasons:

App1.Class1[]

Unfortunately, no further information is available.

Se necesitan metadatos de Browse para el tipo de matriz para poder crear instancia de esta dinámicamente. La siguiente directiva en tiempo de ejecución permite la creación dinámica instancias de Class1[].

<Type Name="App1.Class1[]" Browse="Required Public" />

Vea también