APIs That Rely on Reflection

In some cases, the use of reflection in code isn't obvious, and so the .NET Native tool chain doesn't preserve metadata that is needed at run time. This topic covers some common APIs or common programming patterns that aren't considered part of the reflection API but that rely on reflection to execute successfully. If you use them in your source code, you can add information about them to the runtime directives (.rd.xml) file so that calls to these APIs do not throw a MissingMetadataException exception or some other exception at run time.

Type.MakeGenericType method

You can dynamically instantiate a generic type AppClass<T> by calling the Type.MakeGenericType method by using code like this:

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

For this code to succeed at run time, several items of metadata are required. The first is Browse metadata for the uninstantiated generic type, AppClass<T>:

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

This allows the Type.GetType(String, Boolean) method call to succeed and return a valid Type object.

But even when you add metadata for the uninstantiated generic type, calling the Type.MakeGenericType method throws a MissingMetadataException exception:

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

App1.AppClass`1<System.Int32>.

You can add the following run-time directive to the runtime directives file to add Activate metadata for the specific instantiation over AppClass<T> of System.Int32:

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

Each different instantiation over AppClass<T> requires a separate directive if it's being created with the Type.MakeGenericType method and not used statically.

MethodInfo.MakeGenericMethod method

Given a class Class1 with a generic method GetMethod<T>(T t), GetMethod can be invoked through reflection by using code like this:

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);

To run successfully, this code requires several items of metadata:

  • Browse metadata for the type whose method you want to call.

  • Browse metadata for the method you want to call. If it is a public method, adding public Browse metadata for the containing type includes the method, too.

  • Dynamic metadata for the method you want to call, so that the reflection invocation delegate is not removed by the .NET Native tool chain. If dynamic metadata is missing for the method, the following exception is thrown when the MethodInfo.MakeGenericMethod method is called:

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

The following runtime directives ensure that all required metadata is available:

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

A MethodInstantiation directive is required for each different instantiation of the method that is dynamically invoked, and the Arguments element is updated to reflect each different instantiation argument.

Array.CreateInstance and Type.MakeTypeArray methods

The following example calls the Type.MakeArrayType and Array.CreateInstance methods on a type, Class1.

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

If no array metadata is present, the following error results:

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.

Browse metadata for the array type is required to dynamically instantiate it. The following runtime directive allows dynamic instantiation of Class1[].

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

See also