APIs que Dependem de Reflexão
Em alguns casos, o uso de reflexão no código não é óbvio e, portanto, a cadeia de ferramentas do .NET Native não preserva os metadados necessários em tempo de execução. Este tópico abrange algumas APIs ou padrões de programação comuns que não são consideradas como parte da API de reflexão, mas que dependem de reflexão para serem executados com êxito. Se você usá-los no código-fonte, poderá adicionar informações sobre eles no arquivo de diretivas de runtime (.rd.xml), de modo que as chamadas a essas APIs não gerem uma exceção MissingMetadataException ou outras exceções em runtime.
Método Type.MakeGenericType
Você pode instanciar dinamicamente um tipo genérico AppClass<T>
chamando o método Type.MakeGenericType usando um código da seguinte forma:
var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);
Para que esse código seja bem-sucedido no tempo de execução, vários itens de metadados são necessários. O primeiro é metadados Browse
para o tipo genérico não instanciado, AppClass<T>
:
<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />
Isso permite que a chamada de método Type.GetType(String, Boolean) seja bem-sucedida e retorne um objeto Type válido.
Mesmo quando você adiciona metadados ao tipo genérico não instanciado, uma chamada ao método Type.MakeGenericType gera uma exceção MissingMetadataException:
Essa operação não pode ser executada, pois os metadados do seguinte tipo foram removidos por motivos de desempenho:
App1.AppClass`1<System.Int32>
.
Você pode adicionar a seguinte diretiva de runtime ao arquivo de diretivas de runtime para adicionar metadados Activate
à instanciação específica sobre AppClass<T>
de System.Int32:
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
Activate="Required Public" />
Cada instanciação AppClass<T>
diferente requer uma diretiva separada se estiver sendo criada com o Type.MakeGenericType método e não for usada estaticamente.
Método MethodInfo.MakeGenericMethod
Dada a classe Class1
com um método genérico GetMethod<T>(T t)
, GetMethod
pode ser invocado por meio de reflexão usando um código da seguinte forma:
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 ser executado com êxito, esse código requer vários itens de metadados:
Metadados
Browse
para o tipo cujo método você deseja chamar.Metadados
Browse
para o método que você deseja chamar. Se for um método público, adicionar metadadosBrowse
públicos ao tipo recipiente também inclui o método.Metadados dinâmicos para o método que você deseja chamar, para que o delegado de invocação de reflexão não seja removido pela cadeia de ferramentas do .NET Native. Se os metadados dinâmicos não estiverem presentes para o método, a exceção a seguir é acionada quando o método MethodInfo.MakeGenericMethod é chamado:
MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
As seguintes diretivas de runtime garantem que todos os metadados estão disponíveis:
<Type Name="App1.Class1" Browse="Required PublicAndInternal">
<MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>
A diretiva MethodInstantiation
é necessária para cada instanciação diferente do método é invocada dinamicamente, e o elemento Arguments
é atualizado para refletir cada argumento de instanciação diferente.
Métodos Array.CreateInstance e Type.MakeTypeArray
A exemplo a seguir chama os métodos Type.MakeArrayType e Array.CreateInstance em um tipo Class1
.
Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);
Se não houver nenhum metadado matriz, é apresentado o seguinte erro:
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.
Metadados Browse
para o tipo de matriz são necessários para instanciá-lo dinamicamente. A diretiva de runtime a seguir permite a instanciação dinâmica do Class1[]
.
<Type Name="App1.Class1[]" Browse="Required Public" />