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.


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

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


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

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

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

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

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


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.


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

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.


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.


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.


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


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

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


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.


Hallo, ich habe versehentlich herabgestimmt. Bitte bearbeiten Sie Ihre Antwort, damit ich sie rückgängig machen kann.
Coloboxp
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.