Type.GetType ("namespace.abClassName") retorna nulo

216

Este código:

Type.GetType("namespace.a.b.ClassName")

retorna null.

e eu tenho os usos:

using namespace.a.b;

Atualizar:

O tipo existe, está em uma biblioteca de classes diferente e eu preciso obtê-lo pelo nome da string.

Omu
fonte
Consulte este stackoverflow.com/questions/441680/… para obter informações sobre como obter o nome qualificado do assembly.
#

Respostas:

244

Type.GetType("namespace.qualified.TypeName") só funciona quando o tipo é encontrado no mscorlib.dll ou no assembly atualmente em execução.

Se nenhuma dessas coisas for verdadeira, você precisará de um nome qualificado para montagem :

Type.GetType("namespace.qualified.TypeName, Assembly.Name")
DrPizza
fonte
3
o tipo existe, está em uma biblioteca de classes diferentes, e eu preciso para obtê-lo pelo nome de cadeia
Omu
25
Em vez de usar um nome qualificado para montagem, você pode carregar a montagem por nome - Assembly a = Assembly.Load("SomeLibrary");- e depois carregar o tipo por nome da montagem - Type t = a.GetType("namespace.a.b.ClassName");.
Kenny Evitt
6
Talvez você poderia gostar typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);pode poupar algum aborrecimento, eventualmente,
Felype
A resposta de Felype foi a única que consegui trabalhar.
Rudy Scoggins
Adicione .FirstOrDefault () ao comentário do @Felype #
Leandro
173

Você também pode obter o tipo sem nome qualificado de montagem, mas também com o nome da dll, por exemplo:

Type myClassType = Type.GetType("TypeName,DllName");

Eu tive a mesma situação e funcionou para mim. Eu precisava de um objeto do tipo "DataModel.QueueObject" e tinha uma referência a "DataModel", então obtive o tipo da seguinte maneira:

Type type = Type.GetType("DataModel.QueueObject,DataModel");

A segunda sequência após a vírgula é o nome de referência (nome da DLL).

Asaf Pala
fonte
2
Isso é um 'truque' ou um método real? Não consigo encontrar isso na documentação -_-. By the way, termina minha 1 semana sofrer! obrigado
DnR
1
Esta é uma solução muito mais limpa, eu adoraria ver se existem armadilhas por causa disso.
Cssacksman
4
O formulário usado nesta resposta também é um nome de tipo totalmente qualificado de acordo com a gramática do MSDN (portanto, não é um truque ). O formulário é NamespaceTypeName, AssemblyNameSpeconde AssemblyNameSpecestá o identificador da montagem sem nenhuma propriedade. Mesmo que essa resposta seja essencialmente a mesma que a aceita, presumo que algumas pessoas prefiram isso porque elimina parte do "ruído" que as propriedades da montagem introduzem (por exemplo Version, Culture PublicKeyToken). Felizmente, as propriedades são opcionais .
Martin Liversage
Para tipos aninhados, talvez seja necessário fazer algo comoAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo
Obrigado, ele funciona para a pasta App_Code. Exemplo: Type.GetType ("TypeName, App_Code");
Burak Koray Balc
79

tente usar esse método

 public static Type GetType(string typeName)
        {
            var type = Type.GetType(typeName);
            if (type != null) return type;
            foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = a.GetType(typeName);
                if (type != null)
                    return type;
            }
            return null ;
        }
peyman
fonte
Isso é o que realmente funcionou para mim. Eu tive que ajustar adicionando uma guarnição de substring antes do loop foreach, no entanto, porque passei um nome qualificado para montagem e Assembly.GetType () só funcionará se você excluir as informações da montagem.
Colin
isso parece ótimo, mas e os genéricos usando outros tipos de montagem?
Demetris Leptos
Não funciona para UWP porque AppDomainnão é suportado. Não tenho certeza de quaisquer alternativas.
James M
25
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
    lock (typeCache) {
        if (!typeCache.TryGetValue(typeName, out t)) {
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
                t = a.GetType(typeName);
                if (t != null)
                    break;
            }
            typeCache[typeName] = t; // perhaps null
        }
    }
    return t != null;
}
erikkallen
fonte
1
isso parece ótimo, mas e os genéricos usando outros tipos de montagem?
Demetris Leptos
1
@DemetrisLeptos (eu sei que o comentário é antigo - mas outras pessoas ainda podem estar interessadas): use int index = typeName.IndexOf ('' '); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } Observe que o Tdo tipo genérico é removido.
Bernhard Hiller
25

Se o assembly fizer parte da compilação de um aplicativo ASP.NET, você poderá usar a classe BuildManager:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
LarryBud
fonte
1
Esta é uma resposta fantástica e deve estar no topo da página. Funciona como um encanto e é absolutamente simples em comparação com a maneira antiga de obter o nome do tipo qualificado da montagem.
Graham
isso é incrivelmente simples e direto, você pode me ajudar com a otimização do desempenho de objetos de reflexão?
22418 Alok
15

se a sua classe não estiver na área atual, você deve fornecer o nome qualificado e este código mostra como obter o nome qualificado da classe

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

e então você pode obter o tipo com qualificadoName

Type elementType = Type.GetType(qualifiedName);
Numan KIZILIRMAK
fonte
8

Se for um tipo aninhado, você pode estar se esquecendo de transformar a. para um +

Independentemente disso, typeof( T).FullNamedirá o que você deveria estar dizendo

EDIT: BTW, os usos (como eu tenho certeza que você sabe) são apenas diretrizes para o compilador em tempo de compilação e, portanto, não podem ter nenhum impacto no sucesso da chamada da API. (Se você tivesse referências de projeto ou montagem, isso poderia ter tido influência - portanto, as informações não são inúteis, são necessárias algumas filtragem ...)

Ruben Bartelink
fonte
Oh meu! Você sabe onde esta sintaxe "+" é explicada?
Protector one
1
Protectorone, eu aprendi isso no amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC, mas isso é um pouco antiquado. Posso recomendar amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… como um livro infalivelmente útil para todos os .NET devs + inclui isso? A linha inferior é que, para Tipos, o CLR possui apenas o espaço para nome e o nome - um tipo aninhado não é diretamente endereçável. Assim, uma linguagem, se ele tem um tipo aninhado conceito começa a fazer o que precisa (embora, em geral, a maioria dos langs usar um +separador)
Ruben Bartelink
6

Estou abrindo controles de usuário, dependendo de quais controles o usuário tem acesso especificado em um banco de dados. Então, eu usei esse método para obter o TypeName ...

Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))

Portanto, agora é possível usar o valor retornado em strType para criar uma instância desse objeto.

Stephan
fonte
reabrindo um tópico épico ... parabéns. No entanto, tenho que recusar sua resposta, porque o TO realmente conhece o Typename e deseja obter o tipo dele. Btw .: qual método você faz referência por <c> GetType (Namespace.ClassName) </c>, se for Type.GetType, funcionará apenas nos tipos que estão dentro do assembly em execução atual ou no mscorlib, mas como TO nenhum dessas condições se aplica.
precisa saber é o seguinte
2
@HimBromBeere Obrigado pela votação inativa. São pessoas como você que me desmotivam para publicar minhas descobertas. Ainda estou aprendendo desenvolvimento e apenas tentando ajudar os outros. E agora você espera que eu responda sua pergunta? A propósito, eu respondi a pergunta corretamente. A classe que eu estava criando uma instância reside em um projeto diferente e é preciso usar um nome AssemblyQualified por causa disso. Então, leia o restante dos comentários antes da votação. "o tipo existe, está em uma biblioteca de classes diferentes, e eu preciso para obtê-lo pelo nome string - Omu"
Stephan
6

Quando tenho apenas o nome da classe, uso este:

Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();
Marchino
fonte
5

Como Type.GetType (String) precisa do Type.AssemblyQualifiedName, você deve usar Assembly.CreateQualifiedName (String, String) .

string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);

A Version, Culture e PublicKeyToken não são necessárias, por assemblyNameisso é possível usar MyAssembly.GetName (). Name.

Sobre Type.GetType (String) :

Se o tipo estiver no assembly atualmente em execução ou no Mscorlib.dll, será suficiente fornecer o nome do tipo qualificado pelo seu espaço para nome.

Florian Talour
fonte
4

Se a montagem for referenciada e a classe visível:

typeof(namespace.a.b.ClassName)

GetType retorna nulo porque o tipo não foi encontrado, com typeof, o compilador pode ajudá-lo a descobrir o erro.

Guillaume
fonte
o tipo existe, está em uma biblioteca de classes diferentes, e eu preciso para obtê-lo pelo nome de cadeia
Omu
4

Tente usar o nome completo do tipo que inclui as informações da montagem, por exemplo:

string typeName = @"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);

Eu tive a mesma situação quando estava usando apenas o namesspace.classname para obter o tipo de uma classe em um assembly diferente e não funcionou. Só funcionou quando incluí as informações de montagem na minha string de tipo, como mostrado acima.

Ismail Hawayel
fonte
3

Verifique se a vírgula está diretamente após o nome completo

typeof(namespace.a.b.ClassName, AssemblyName)

Como isso não vai funcionar

typeof(namespace.a.b.ClassName ,AssemblyName)

Fiquei perplexo por alguns dias neste

jack_tux
fonte
2

Para mim, um "+" era a chave! Esta é a minha classe (é aninhada):

namespace PortalServices
{
public class PortalManagement : WebService
{
    public class Merchant
    {}
}
}

e esta linha de código funcionou:

Type type = Type.GetType("PortalServices.PortalManagement+Merchant");
Arash Masir
fonte
1

Essa solução acima parece ser a melhor para mim, mas não funcionou para mim; portanto, fiz o seguinte:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);

Type myType = Type.GetType(typeAssemblyQualifiedName);

A pré-condição é que você saiba o caminho da montagem. No meu caso, eu sei porque é uma montagem criada a partir de outro projeto interno e incluída na pasta bin do nosso projeto.

Caso seja importante usar o Visual Studio 2013, meu .NET de destino é 4.0. Este é um projeto do ASP.NET, por isso estou obtendo um caminho absoluto HttpContext. No entanto, o caminho absoluto não é um requisito, como parece do MSDN no AssemblyQualifiedNames

Ozair Kafray
fonte
0

Eu trapaceei. Como os tipos que eu quero criar (por nome) estão todos em uma dll que eu controle, bastai colocar um método estático na dll na montagem que usa um nome simples e chama type.GetType a partir desse contexto e retorna o resultado .

O objetivo original era que o tipo pudesse ser especificado pelo nome nos dados de configuração. Desde então, mudei o código para que o usuário especificasse um formato para processar. As classes de manipulador de formato implementam uma interface que determina se o tipo pode analisar o formato especificado. Em seguida, uso a reflexão para encontrar tipos que implementam a interface e encontrar um que lide com o formato. Portanto, agora a configuração especifica um nome de formato, um tipo não específico. O código de reflexão pode olhar para dlls adjacentes e carregar, para que eu tenha uma arquitetura de plug-in de um tipo pobre.

Darrel Lee
fonte
Olá, meu voto foi diminuído por engano. Edite sua resposta para que eu possa desfazê-la.
Coloboxp