Type.GetType ("namespace.abClassName") gibt null zurück

216

Dieser Code:

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

kehrt zurück null.

und ich habe in den usings:

using namespace.a.b;

Aktualisieren:

Der Typ existiert, er befindet sich in einer anderen Klassenbibliothek und ich muss ihn anhand des Stringnamens abrufen.

Omu
quelle
Weitere Informationen zum Abrufen des qualifizierten Baugruppennamens finden Sie unter stackoverflow.com/questions/441680/… .
Polyfun

Antworten:

244

Type.GetType("namespace.qualified.TypeName") Funktioniert nur, wenn der Typ entweder in mscorlib.dll oder in der aktuell ausgeführten Assembly gefunden wird.

Wenn keines dieser Dinge zutrifft, benötigen Sie einen Assembly-qualifizierten Namen :

Type.GetType("namespace.qualified.TypeName, Assembly.Name")
DrPizza
quelle
3
Der Typ existiert, er befindet sich in einer anderen Klassenbibliothek und ich muss ihn anhand des
Stringnamens
25
Anstatt einen Assembly-qualifizierten Namen zu verwenden, können Sie die Assembly nach Namen Assembly a = Assembly.Load("SomeLibrary");laden - - und dann den Typ nach Namen aus der Assembly laden - Type t = a.GetType("namespace.a.b.ClassName");.
Kenny Evitt
6
Vielleicht typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);
möchten
Felypes Antwort war die einzige, die ich zum Arbeiten bringen konnte.
Rudy Scoggins
Fügen Sie .FirstOrDefault () zu @Felype Kommentar hinzu
Leandro
173

Sie können den Typ auch ohne Assembly-qualifizierten Namen abrufen, aber auch mit dem DLL-Namen, zum Beispiel:

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

Ich hatte die gleiche Situation und es hat bei mir funktioniert. Ich brauchte ein Objekt vom Typ "DataModel.QueueObject" und hatte einen Verweis auf "DataModel", also bekam ich den Typ wie folgt:

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

Die zweite Zeichenfolge nach dem Komma ist der Referenzname (DLL-Name).

Asaf Pala
quelle
2
Ist das ein "Trick" oder eine tatsächliche Methode? Ich kann dies nicht in der Dokumentation -_- finden. Übrigens endet meine 1 Woche leiden! danke
DnR
1
Dies ist eine viel sauberere Lösung. Ich würde gerne sehen, ob es aus diesem Grund Fallstricke gibt.
cossacksman
4
Das in dieser Antwort verwendete Formular ist auch ein vollständig qualifizierter Typname gemäß der MSDN-Grammatik (es handelt sich also nicht um einen Trick ). Die Form ist , NamespaceTypeName, AssemblyNameSpecwo AssemblyNameSpecdie Kennung der Baugruppe ohne Eigenschaften. Auch wenn diese Antwort im Wesentlichen das gleiche ist wie die akzeptierte Ich gehe davon aus, dass einige Leute dieses vorziehen , weil es mit einigen des „Lärm“ beseitigt , dass die Montageeigenschaften einführen (zB Version, Culture PublicKeyToken). Glücklicherweise sind die Eigenschaften optional .
Martin Liversage
Für verschachtelte Typen müssen Sie möglicherweise etwas tun wieAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo
Danke, es funktioniert für den App_Code-Ordner. Beispiel: Type.GetType ("TypeName, App_Code");
Burak Koray Balcı
79

Versuchen Sie es mit dieser Methode

 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
quelle
Das hat bei mir tatsächlich funktioniert. Ich musste jedoch vor der foreach-Schleife eine Teilstring-Trimmung hinzufügen, da ich einen Assembly-qualifizierten Namen übergeben habe und Assembly.GetType () nur funktioniert, wenn Sie die Assembly-Informationen ausschließen.
Colin
Das sieht gut aus, aber was ist mit Generika, die andere Baugruppentypen verwenden?
Demetris Leptos
Funktioniert nicht für UWP, da AppDomaines nicht unterstützt wird. Ich bin mir keiner Alternativen sicher.
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
quelle
1
Das sieht gut aus, aber was ist mit Generika, die andere Baugruppentypen verwenden?
Demetris Leptos
1
@DemetrisLeptos (Ich weiß, dass der Kommentar alt ist - aber andere Leute sind möglicherweise noch interessiert): use int index = typeName.IndexOf ('`'); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } Beachten Sie, dass der Tgenerische Typ entfernt ist.
Bernhard Hiller
25

Wenn die Assembly Teil des Builds einer ASP.NET-Anwendung ist, können Sie die BuildManager-Klasse verwenden:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
LarryBud
quelle
1
Dies ist eine fantastische Antwort und sollte weiter oben auf der Seite stehen. Funktioniert wie ein Zauber und ist im Vergleich zu der alten Methode, den qualifizierten Typnamen der Baugruppe zu erhalten, kinderleicht.
Graham
Das ist erstaunlich einfach und genau richtig. Können Sie mir bei der Leistungsoptimierung von Reflexionsobjekten helfen?
Alok
15

Wenn sich Ihre Klasse nicht in der aktuellen Assambly befindet, müssen Sie den qualifizierten Namen angeben. Dieser Code zeigt, wie Sie den qualifizierten Namen der Klasse erhalten

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

und dann können Sie Typ mit qualifiziertem Namen erhalten

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

Wenn es sich um einen verschachtelten Typ handelt, vergessen Sie möglicherweise, a zu transformieren. zu einem +

Ungeachtet, typeof( T).FullName wird Ihnen sagen, was Sie sagen sollten

BEARBEITEN: Übrigens sind die Verwendungen (wie Sie sicher wissen) nur Anweisungen an den Compiler zur Kompilierungszeit und können daher keinen Einfluss auf den Erfolg des API-Aufrufs haben. (Wenn Sie Projekt- oder Baugruppenreferenzen hatten, könnte dies möglicherweise Einfluss gehabt haben - daher sind die Informationen nicht nutzlos, es sind nur einige Filter erforderlich ...)

Ruben Bartelink
quelle
Oh mein! Wissen Sie, wo diese "+" - Syntax erklärt wird?
Beschützer ein
1
Protectorone Ich habe es von amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC gelernt, aber das ist etwas veraltet. Kann ich amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… als ein absolut nützliches Buch für alle .NET-Entwickler empfehlen, das dies enthält? Unter dem Strich hat die CLR für Typen nur den Namespace und den Namen - ein verschachtelter Typ ist nicht direkt adressierbar. Daher kann eine Sprache, wenn sie ein verschachteltes Typkonzept hat, das tun, was sie benötigt (obwohl die meisten langs im Allgemeinen ein +Trennzeichen verwenden)
Ruben Bartelink
6

Ich öffne Benutzersteuerelemente in Abhängigkeit davon, auf welche Benutzersteuerelemente der Benutzer Zugriff hat, die in einer Datenbank angegeben sind. Also habe ich diese Methode verwendet, um den TypeName zu erhalten ...

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

Jetzt kann man den in strType zurückgegebenen Wert verwenden, um eine Instanz dieses Objekts zu erstellen.

Stephan
quelle
Wiedereröffnung eines episch alten Themas ... Glückwunsch. Allerdings muss ich Ihre Antwort ablehnen, da der TO den Typenamen tatsächlich kennt und den Typ daraus erhalten möchte. Übrigens: Auf welche Methode verweisen Sie mit <c> GetType (Namespace.ClassName) </ c>? dieser Bedingungen gilt.
HimBromBeere
2
@HimBromBeere Danke für die Abstimmung. Es sind Menschen wie Sie, die mich demotivieren, meine Ergebnisse zu veröffentlichen. Ich lerne immer noch Entwicklung und versuche nur, anderen zu helfen. Und jetzt erwarten Sie, dass ich Ihre Frage beantworte? Ich habe die Frage übrigens richtig beantwortet. Die Klasse, für die ich eine Instanz erstellt habe, befindet sich in einem anderen Projekt, und aus diesem Grund muss ein AssemblyQualified-Name verwendet werden. Bitte lesen Sie den Rest der Kommentare, bevor Sie abstimmen. "Der Typ existiert, er befindet sich in einer anderen Klassenbibliothek und ich muss ihn mit dem String-Namen - Omu" abrufen
Stephan
6

Wenn ich nur den Klassennamen habe, verwende ich diesen:

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

Da Type.GetType (String) den Type.AssemblyQualifiedName benötigt , sollten Sie Assembly.CreateQualifiedName (String, String) verwenden .

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

Die Version, Culture und PublicKeyToken sind nicht erforderlich assemblyName, daher können Sie MyAssembly.GetName (). Name verwenden.

Über Type.GetType (String) :

Befindet sich der Typ in der aktuell ausgeführten Assembly oder in Mscorlib.dll, reicht es aus, den durch seinen Namespace qualifizierten Typnamen anzugeben.

Florian Talour
quelle
4

Wenn auf die Assembly verwiesen wird und die Klasse sichtbar ist:

typeof(namespace.a.b.ClassName)

GetType gibt null zurück, da der Typ nicht gefunden wird. Mit typeof kann der Compiler Ihnen helfen, den Fehler herauszufinden.

Guillaume
quelle
Der Typ existiert, er befindet sich in einer anderen Klassenbibliothek und ich muss ihn über den Namen der Zeichenfolge
abrufen
4

Versuchen Sie, den vollständigen Typnamen zu verwenden, der die Baugruppeninformationen enthält, zum Beispiel:

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

Ich hatte die gleiche Situation, als ich nur den Namen namesspace.classname verwendete, um den Typ einer Klasse in einer anderen Assembly abzurufen, und es würde nicht funktionieren. Funktionierte nur, wenn ich die Assembly-Informationen wie oben gezeigt in meine Typzeichenfolge aufgenommen habe.

Ismail Hawayel
quelle
3

Stellen Sie sicher, dass das Komma direkt hinter dem vollständig qualifizierten Namen steht

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

Da das nicht funktioniert

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

Ich war ein paar Tage lang ratlos

jack_tux
quelle
2

Für mich war ein "+" der Schlüssel! Dies ist meine Klasse (es ist eine verschachtelte):

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

und diese Codezeile funktionierte:

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

Diese obige Lösung scheint mir die beste zu sein, aber sie hat bei mir nicht funktioniert, also habe ich sie wie folgt gemacht:

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

Type myType = Type.GetType(typeAssemblyQualifiedName);

Voraussetzung ist, dass Sie den Pfad der Baugruppe kennen. In meinem Fall weiß ich es, weil dies eine Assembly ist, die aus einem anderen internen Projekt erstellt wurde und im bin-Ordner unseres Projekts enthalten ist.

Für den Fall, dass ich Visual Studio 2013 verwende, ist mein Ziel .NET 4.0. Dies ist ein ASP.NET-Projekt, daher erhalte ich den absoluten Pfad über HttpContext. Ein absoluter Pfad ist jedoch keine Voraussetzung, wie es aus MSDN auf AssemblyQualifiedNames hervorgeht

Ozair Kafray
quelle
0

I habe betrogen. Da die Typen, die ich erstellen möchte (nach Namen), alle in einer von mir gesteuerten DLL enthalten sind, füge ich einfach eine statische Methode in die DLL in der Assembly ein, die einen einfachen Namen annimmt, und rufe type.GetType aus diesem Kontext auf und gibt das Ergebnis zurück .

Der ursprüngliche Zweck bestand darin, dass der Typ in den Konfigurationsdaten namentlich angegeben werden konnte. Ich habe seitdem den Code so geändert, dass der Benutzer ein zu verarbeitendes Format angegeben hat. Die Formathandlerklassen implementieren eine Schnittstelle, die bestimmt, ob der Typ das angegebene Format analysieren kann. Ich benutze dann Reflection, um Typen zu finden, die die Schnittstelle implementieren, und einen, der das Format behandelt. Die Konfiguration gibt nun einen Formatnamen an, keinen bestimmten Typ. Der Reflection-Code kann benachbarte DLLs betrachten und laden, sodass ich die Plug-In-Architektur eines armen Mannes habe.

Darrel Lee
quelle
Hallo, ich habe versehentlich herabgestimmt. Bitte bearbeiten Sie Ihre Antwort, damit ich sie rückgängig machen kann.
Coloboxp