Compartilhar via


Métodos System.Type.GetType

Este artigo fornece comentários complementares à documentação de referência para esta API.

Use a sobrecarga do GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean, Boolean) método e suas sobrecargas associadas (GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>) e GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean)) para substituir a implementação padrão do GetType método por implementações mais flexíveis. Ao fornecer seus próprios métodos que resolvem os nomes dos tipos e dos assemblies que os contêm, você pode fazer o seguinte:

  • Controlar de qual versão de um assembly um tipo é carregado.
  • Fornecer outro local para procurar um nome de tipo que não inclua um nome de assembly.
  • Carregar assemblies usando nomes parciais.
  • Retornar subclasses de System.Type que não são criadas pelo Common Language Runtime (CLR).

Por exemplo, na serialização tolerante à versão, esse método permite que você pesquise por um conjunto de código mais adequado usando um nome parcial. Outras sobrecargas do método GetType exigem um nome de tipo qualificado para assembly, que inclui o número da versão.

Implementações alternativas do sistema de tipos podem precisar retornar subclasses de System.Type que não são criadas pelo CLR; todos os tipos retornados por outras sobrecargas do método GetType são tipos de tempo de execução.

Notas de utilização

Essa sobrecarga de método e as sobrecargas associadas analisam typeName no nome de um tipo e o nome de um assembly e resolvem os nomes. A resolução do nome do assembly ocorre antes da resolução do nome do tipo, pois um nome de tipo deve ser resolvido no contexto de um assembly.

Observação

Se você não estiver familiarizado com o conceito de nomes de tipo qualificados para assembly, consulte a propriedade AssemblyQualifiedName.

Se typeName não for um nome qualificado para assembly, a resolução do assembly será ignorada. Nomes de tipo não qualificados podem ser resolvidos no contexto de mscorlib.dll/System.Private.CoreLib.dll ou no assembly em execução no momento, ou você pode fornecer um assembly no parâmetro typeResolver. Os efeitos de incluir ou omitir o nome do assembly para diferentes tipos de resolução de nomes são exibidos em forma de tabela na seção Resolução de nomes mistos.

Notas de uso geral:

  • Não passe métodos para assemblyResolver ou typeResolver se eles vêm de chamadores desconhecidos ou não confiáveis. Use apenas os métodos que você fornece ou com os quais esteja familiarizado.

    Cuidado

    Usar métodos de chamadores desconhecidos ou não confiáveis pode resultar em elevação de privilégio para código mal-intencionado.

  • Se você omitir os parâmetros assemblyResolver e/ou typeResolver, o valor do parâmetro throwOnError será passado para os métodos que executam a resolução padrão.

  • Se throwOnError for true, esse método gerará um TypeLoadException quando typeResolver retornar nulle um FileNotFoundException quando assemblyResolver retornar null.

  • Esse método não captura exceções geradas por assemblyResolver e typeResolver. Você é responsável por quaisquer exceções geradas pelos métodos resolvedores.

Resolver assemblies

O método assemblyResolver recebe um objeto AssemblyName, que é produzido ao analisar o nome do assembly da cadeia de caracteres incluído em typeName. Se typeName não contiver um nome de assembly, assemblyResolver não será chamado e null será passado para typeResolver.

Caso assemblyResolver não seja fornecido, a sondagem de assembly padrão será utilizada para localizar o assembly. Se assemblyResolver estiver fornecido, o método GetType não fará a sondagem padrão. Nesse caso, é necessário garantir que assemblyResolver consiga lidar com todos os assemblies transmitidos.

O método assemblyResolver deverá retornar null se o assembly não puder ser resolvido. Se assemblyResolver retornar null, typeResolver não será chamado e nenhum processamento adicional ocorrerá; além disso, se throwOnError for true, será lançado um FileNotFoundException.

Se o AssemblyName que é passado para assemblyResolver é um nome parcial, uma ou mais de suas partes são null. Por exemplo, se não tiver nenhuma versão, a Version propriedade será null. Se a Version propriedade, a CultureInfo propriedade e o GetPublicKeyToken método retornarem null, somente o nome simples do assembly foi fornecido. O assemblyResolver método pode usar ou ignorar todas as partes do nome do assembly.

Os efeitos de diferentes opções de resolução de assembly são exibidos como uma tabela na seção Resolução de nomes mistos, para nomes de tipo simples e qualificados por assembly.

Resolver tipos

Se typeName não especificar um nome de assembly, typeResolver sempre será chamado. Se typeName especificar um nome de assembly, typeResolver será chamado somente quando o nome do assembly for resolvido com êxito. Se assemblyResolver ou a sondagem de assembly padrão retornar null, typeResolver não será chamado.

O typeResolver método recebe três argumentos:

  • O assembly a ser pesquisado ou null se typeName não contiver um nome de assembly.
  • O nome simples do tipo. No caso de um tipo aninhado, este é o tipo externo mais abrangente. No caso de um tipo genérico, esse é o nome simples do tipo genérico.
  • Um valor booleano que será true se o caso dos nomes de tipos precisar ser ignorado.

A implementação determina a maneira como esses argumentos são usados. O typeResolver método deverá retornar null se não puder resolver o tipo. Se typeResolver retornar null e throwOnError for true, essa sobrecarga de GetType lançará um TypeLoadException.

Os efeitos de diferentes opções de resolução de tipo são exibidos como uma tabela na seção Resolução de nomes mistos, para nomes de tipo simples e qualificados por assembly.

Resolver tipos aninhados

Se typeName for um tipo aninhado, somente o nome do tipo mais externo que contém será transmitido para typeResolver. Quando `typeResolver` retorna esse tipo, o método `GetNestedType` é chamado recursivamente até que o tipo aninhado mais interno seja resolvido.

Resolver tipos genéricos

O GetType é chamado recursivamente para resolver tipos genéricos: primeiro para resolver o tipo genérico em si e, em seguida, para resolver seus argumentos de tipo. Se um argumento de tipo for genérico, GetType será chamado recursivamente para resolver seus argumentos de tipo e assim por diante.

A combinação de assemblyResolver e typeResolver que você fornece deve ser capaz de resolver todos os níveis dessa recursão. Por exemplo, suponha que você forneça um assemblyResolver que controla o carregamento de MyAssembly. Suponha que você queira resolver o tipo Dictionary<string, MyType> genérico (Dictionary(Of String, MyType) no Visual Basic). Você pode transmitir o seguinte nome de tipo genérico:

"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"

O MyType é o único argumento de tipo qualificado por assembly. Os nomes das classes Dictionary<TKey,TValue> e String não são qualificados por assembly. O typeResolver deve ser capaz de lidar com um assembly ou null, pois ele receberá null para Dictionary<TKey,TValue> e String. Ele pode lidar com esse caso chamando uma sobrecarga do método GetType que usa uma cadeia de caracteres, pois os dois nomes de tipo não qualificados estão em mscorlib.dll/System.Private.CoreLib.dll:

Type t = Type.GetType(test,
                      (aName) => aName.Name == "MyAssembly" ?
                          Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : null,
                      (assem, name, ignore) => assem == null ?
                          Type.GetType(name, false, ignore) :
                              assem.GetType(name, false, ignore)
                     );
let t =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else null),
        fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr))

O método assemblyResolver não é chamado para o tipo de dicionário e o tipo de cadeia de caracteres, pois esses nomes de tipo não são qualificados por assembly.

Agora suponha que, em vez de System.String, o primeiro tipo de argumento genérico seja YourType, de YourAssembly:

"System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]"

Como esse assembly não é mscorlib.dll/System.Private.CoreLib.dll nem o assembly que está sendo executado atualmente, você não pode resolver YourType sem um nome qualificado por assembly. Como o seu assemblyResolve será chamado recursivamente, deve ser capaz de tratar esse caso. Em vez de retornar null para assemblies diferentes de MyAssembly, ele agora executa uma carga de assembly usando o objeto fornecido AssemblyName.

Type t2 = Type.GetType(test,
                       (aName) => aName.Name == "MyAssembly" ?
                           Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") :
                           Assembly.Load(aName),
                       (assem, name, ignore) => assem == null ?
                           Type.GetType(name, false, ignore) :
                               assem.GetType(name, false, ignore), true
                      );
let t2 =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else Assembly.Load aName),
        (fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr)), true)

Resolver nomes de tipo com caracteres especiais

Alguns caracteres têm significados especiais em nomes qualificados por assembly. Se um nome de tipo simples contiver esses caracteres, os caracteres causarão erros de análise quando o nome simples fizer parte de um nome qualificado por assembly. Para evitar os erros de análise, você deve escapar dos caracteres especiais com uma barra invertida antes de transmitir o nome qualificado por assembly para o método GetType. Por exemplo, se um tipo for nomeado Strange]Type, o caractere de escape deverá ser adicionado à frente do colchete da seguinte maneira: Strange\]Type.

Observação

Nomes com esses caracteres especiais não podem ser criados no Visual Basic ou C#, mas podem ser criados usando CIL (linguagem intermediária comum) ou emitindo assemblies dinâmicos.

A tabela a seguir mostra os caracteres especiais para nomes de tipo.

Personagem Significado
, (vírgula) Delimitador para nomes qualificados por assembly.
[] (colchetes) Como um par de sufixos, indica um tipo de matriz; como um par de delimitadores, delimita listas de argumentos genéricos e nomes qualificados por assembly.
& (e comercial) Como sufixo, indica que um tipo é um tipo de referência.
* (asterisco) Como sufixo, indica que um tipo é um tipo de ponteiro.
+ (mais) Delimitador para tipos aninhados.
\ (barra invertida) Caractere de escape.

Propriedades como AssemblyQualifiedName retornam cadeias de caracteres com escape corretamente. Você deve transmitir corretamente as cadeias de caracteres com escape para o método GetType. Por sua vez, o método GetType transmite nomes com escape corretos para typeResolver e para os métodos de resolução de tipo padrão. Se você precisar comparar um nome com um nome sem escape em typeResolver, será necessário remover os caracteres de escape.

Resolução de nomes mistos

A tabela a seguir resume as interações entre assemblyResolver, typeResolver e a resolução de nomes padrão, para todas as combinações de nomes de tipo e de assembly em typeName:

Conteúdo do nome do tipo Método do resolvedor de assembly Método de resolvedor de tipo Resultado
tipo, montagem nulo nulo Equivalente a chamar a sobrecarga do método Type.GetType(String, Boolean, Boolean).
tipo, montagem fornecido nulo assemblyResolver retornará o assembly ou retornará null se não puder resolver o assembly. Se o assembly for resolvido, a sobrecarga do método Assembly.GetType(String, Boolean, Boolean) será usada para carregar o tipo do assembly; caso contrário, não haverá nenhuma tentativa de resolver o tipo.
tipo, montagem nulo fornecido Equivalente a converter o nome do assembly em um objeto AssemblyName e chamar a sobrecarga do método Assembly.Load(AssemblyName) para obter o assembly. Se o assembly for resolvido, ele será passado para typeResolver; caso contrário, typeResolver não será chamado e não haverá mais nenhuma tentativa de resolver o tipo.
tipo, montagem fornecido fornecido assemblyResolver retornará o assembly ou retornará null se não puder resolver o assembly. Se o assembly for resolvido, ele será passado para typeResolver; caso contrário, typeResolver não será chamado e não haverá mais nenhuma tentativa de resolver o tipo.
tipo nulo, fornecido nulo Equivalente a chamar a sobrecarga do método Type.GetType(String, Boolean, Boolean). Como o nome do assembly não é fornecido, somente mscorlib.dll/System.Private.CoreLib.dll e o assembly em execução no momento são pesquisados. Se assemblyResolver for fornecido, será ignorado.
tipo nulo, fornecido fornecido typeResolver é chamado, e em seguida, null é transmitido para o assembly. typeResolver pode fornecer um tipo de qualquer assembly, incluindo assemblies que carrega para esse propósito. Se assemblyResolver for fornecido, será ignorado.
assembleia nulo, fornecido nulo, fornecido Um FileLoadException é gerado, porque o nome do assembly é interpretado como se fosse um nome de tipo qualificado de assembly. Isso resulta em um nome de assembly inválido.