Type.GetType («namespace.abClassName») renvoie null

216

Ce code:

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

retourne null.

et j'ai dans les utilisations:

using namespace.a.b;

Mettre à jour:

Le type existe, il se trouve dans une bibliothèque de classes différente, et j'ai besoin de l'obtenir par nom de chaîne.

Omu
la source
Consultez ce stackoverflow.com/questions/441680/… pour savoir comment obtenir le nom qualifié de l'assembly.
Polyfun

Réponses:

244

Type.GetType("namespace.qualified.TypeName") ne fonctionne que lorsque le type se trouve dans mscorlib.dll ou l'assembly en cours d'exécution.

Si aucune de ces choses n'est vraie, vous aurez besoin d'un nom qualifié d'assembly :

Type.GetType("namespace.qualified.TypeName, Assembly.Name")
DrPizza
la source
3
le type existe, il est dans une bibliothèque de classe différente, et je dois l'obtenir par nom de chaîne
Omu
25
Au lieu d'utiliser un nom qualifié d'assembly, vous pouvez charger l'assembly par nom - Assembly a = Assembly.Load("SomeLibrary");- puis charger le type par nom à partir de l'assembly - Type t = a.GetType("namespace.a.b.ClassName");.
Kenny Evitt
6
Peut-être que vous aimeriez typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);peut-être économiser des tracas, éventuellement
Felype
La réponse de Felype fut la seule que je pus travailler.
Rudy Scoggins
Ajoutez .FirstOrDefault () au commentaire @Felype
Leandro
173

Vous pouvez également obtenir le type sans nom qualifié d'assembly mais également avec le nom de la DLL, par exemple:

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

J'ai eu la même situation et cela a fonctionné pour moi. J'avais besoin d'un objet de type "DataModel.QueueObject" et j'avais une référence à "DataModel" alors j'ai obtenu le type comme suit:

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

La deuxième chaîne après la virgule est le nom de référence (nom de la DLL).

Asaf Pala
la source
2
Est-ce une «astuce» ou une méthode réelle? Je ne trouve pas cela dans la documentation -_-. Soit dit en passant, cela met fin à ma souffrance d'une semaine! merci
DnR
1
Ceci est une solution beaucoup plus propre, j'aimerais voir s'il y a des pièges à cause de cela.
cosaque
4
Le formulaire utilisé dans cette réponse est également un nom de type complet selon la grammaire MSDN (ce n'est donc pas une astuce ). La forme est NamespaceTypeName, AssemblyNameSpecAssemblyNameSpecest l'identifiant de l'assembly sans aucune propriété. Même si cette réponse est essentiellement la même que celle acceptée, je suppose que certaines personnes préfèrent cela parce qu'elle supprime une partie du «bruit» que les propriétés d'assemblage introduisent (par exemple Version, Culture PublicKeyToken). Heureusement, les propriétés sont facultatives .
Martin Liversage
Pour les types imbriqués, vous devrez peut-être faire quelque chose commeAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo
Merci, cela fonctionne pour le dossier App_Code. Exemple: Type.GetType ("TypeName, App_Code");
Burak Koray Balcı
79

essayez d'utiliser cette méthode

 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
la source
C'est ce qui a réellement fonctionné pour moi. Cependant, j'ai dû modifier en ajoutant une sous-chaîne avant la boucle foreach, car j'ai transmis un nom qualifié d'assembly, et Assembly.GetType () ne fonctionne que si vous excluez les informations d'assembly.
Colin
cela a l'air génial, mais qu'en est-il des génériques utilisant d'autres types d'assemblage?
Demetris Leptos
Ne fonctionne pas pour UWP car AppDomainn'est pas pris en charge. Je ne suis sûr d'aucune alternative.
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
la source
1
cela a l'air génial, mais qu'en est-il des génériques utilisant d'autres types d'assemblage?
Demetris Leptos
1
@DemetrisLeptos (je sais que le commentaire est ancien - mais d'autres personnes peuvent toujours être intéressées): utilisez int index = typeName.IndexOf ('' '); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } Notez que le Ttype générique est supprimé.
Bernhard Hiller
25

Si l'assembly fait partie de la génération d'une application ASP.NET, vous pouvez utiliser la classe BuildManager:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
LarryBud
la source
1
C'est une réponse fantastique et devrait être plus haut sur la page. Fonctionne comme un charme et est très simple par rapport à l'ancienne façon d'obtenir le nom de type qualifié de l'assembly.
Graham
c'est incroyablement simple et parfait, pouvez-vous m'aider à optimiser les performances des objets de réflexion?
Alok
15

si votre classe n'est pas en cours d'assemblage, vous devez donner qualifiéName et ce code montre comment obtenir un nom qualifié de classe

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

puis vous pouvez obtenir le type avec qualifiéName

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

S'il s'agit d'un type imbriqué, vous oubliez peut-être de transformer a. à un +

Quoi qu'il en soit, typeof( T).FullNamevous dira ce que vous devriez dire

EDIT: BTW les utilisations (comme je suis sûr que vous le savez) ne sont que des directives pour le compilateur au moment de la compilation et ne peuvent donc avoir aucun impact sur le succès de l'appel d'API. (Si vous aviez des références de projet ou d'assemblage, cela pourrait potentiellement avoir une influence - par conséquent, les informations ne sont pas inutiles, il suffit d'un peu de filtrage ...)

Ruben Bartelink
la source
Oh mon! Savez-vous où cette syntaxe "+" - est expliquée?
Protector one
1
Protectorone Je l'ai appris de amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC, mais c'est un peu daté. Puis-je recommander amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… comme un livre incontestablement utile pour tous les développeurs .NET + inclut cela? En fin de compte, pour les types, le CLR n'a que l'espace de noms et le nom - un type imbriqué n'est pas directement adressable. Par conséquent, un langage, s'il a un concept de type imbriqué, fait ce dont il a besoin (bien qu'en général la plupart des langages utilisent un +séparateur)
Ruben Bartelink
6

J'ouvre les contrôles utilisateur en fonction des contrôles utilisateur auxquels l'utilisateur a accès spécifiés dans une base de données. J'ai donc utilisé cette méthode pour obtenir le TypeName ...

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

Alors maintenant, on peut utiliser la valeur retournée dans strType pour créer une instance de cet objet.

Stephan
la source
rouvrir un sujet épique ... félicitations. Cependant, je dois voter contre votre réponse parce que le TO connaît réellement le nom de type et veut en obtenir le type. Btw .: quelle méthode référencez-vous par <c> GetType (Namespace.ClassName) </c>, si son Type.GetType ne fonctionnera que sur les types qui se trouvent dans votre assembly en cours d'exécution ou mscorlib, mais comme TO sais aucun de ces conditions s'applique.
HimBromBeere
2
@HimBromBeere Merci pour le vote négatif. Ce sont des gens comme vous qui me démotivent pour publier mes résultats. J'apprends toujours le développement et j'essaie juste d'aider les autres. Et maintenant, vous vous attendez à ce que je réponde à votre question? Soit dit en passant, j'ai répondu correctement à la question. La classe que je créais une instance de réside dans un projet différent et on doit utiliser un nom AssemblyQualified à cause de cela. Veuillez donc lire le reste des commentaires avant de voter. "le type existe, il est dans une bibliothèque de classe différente, et je dois l'obtenir par nom de chaîne - Omu"
Stephan
6

Lorsque je n'ai que le nom de classe, j'utilise ceci:

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

Comme Type.GetType (String) a besoin du Type.AssemblyQualifiedName, vous devez utiliser 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);

La version, la culture et le PublicKeyToken ne sont pas requis, assemblyNamec'est pourquoi vous pouvez utiliser MyAssembly.GetName (). Name.

À propos de Type.GetType (String) :

Si le type se trouve dans l'assembly en cours d'exécution ou dans Mscorlib.dll, il suffit de fournir le nom de type qualifié par son espace de noms.

Florian Talour
la source
4

Si l'assembly est référencé et la classe visible:

typeof(namespace.a.b.ClassName)

GetType renvoie null car le type est introuvable, avec typeof, le compilateur peut vous aider à trouver l'erreur.

Guillaume
la source
le type existe, il est dans une bibliothèque de classes différente, et je dois l'obtenir par nom de chaîne
Omu
4

Essayez d'utiliser le nom de type complet qui inclut les informations d'assembly, par exemple:

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

J'ai eu la même situation lorsque j'utilisais uniquement le namesspace.classname pour obtenir le type d'une classe dans un autre assembly et cela ne fonctionnerait pas. Cela n'a fonctionné que lorsque j'ai inclus les informations d'assemblage dans ma chaîne de caractères, comme indiqué ci-dessus.

Ismail Hawayel
la source
3

Assurez-vous que la virgule se trouve directement après le nom complet

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

Comme cela ne fonctionnera pas

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

J'ai été perplexe pendant quelques jours sur celui-ci

jack_tux
la source
2

Pour moi, un "+" était la clé! Voici ma classe (elle est imbriquée):

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

et cette ligne de code a fonctionné:

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

Cette solution ci-dessus semble être la meilleure pour moi, mais cela n'a pas fonctionné pour moi, alors je l'ai fait comme suit:

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

Type myType = Type.GetType(typeAssemblyQualifiedName);

La condition préalable est que vous connaissiez le chemin de l'assemblage. Dans mon cas, je le sais car il s'agit d'un assemblage construit à partir d'un autre projet interne et inclus dans le dossier bin de notre projet.

Si cela importe, j'utilise Visual Studio 2013, mon .NET cible est 4.0. Ceci est un projet ASP.NET, donc je reçois un chemin absolu via HttpContext. Cependant, le chemin absolu n'est pas une exigence comme il semble de MSDN sur AssemblyQualifiedNames

Ozair Kafray
la source
0

J'ai triché. Étant donné que les types que je veux créer (par nom) sont tous dans une DLL que je contrôle, je viens de mettre une méthode statique dans la DLL dans l'assembly qui prend un nom simple et appelle type.GetType à partir de ce contexte et renvoie le résultat .

Le but initial était que le type puisse être spécifié par son nom dans les données de configuration. J'ai depuis changé le code pour que l'utilisateur spécifie un format à traiter. Les classes de gestionnaire de format implémentent une interface qui détermine si le type peut analyser le format spécifié. J'utilise ensuite la réflexion pour trouver les types qui implémentent l'interface et en trouver un qui gère le format. Alors maintenant, la configuration spécifie un nom de format, pas un type spécifique. Le code de réflexion peut regarder les DLL adjacentes et les charger, donc j'ai une architecture de plug-in pour les pauvres.

Darrel Lee
la source
Bonjour, j'ai rétrogradé par erreur, veuillez modifier votre réponse afin que je puisse l'annuler.
coloboxp