Type.GetType ("namespace.abClassName") restituisce null


222

Questo codice:

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

ritorna null.

e ho negli usi:

using namespace.a.b;

Aggiornare:

Il tipo esiste, si trova in una libreria di classi diversa e ho bisogno di ottenerlo per nome di stringa.


Vedi questo stackoverflow.com/questions/441680/… per informazioni su come ottenere il nome qualificato dell'assembly.
Polyfun

Risposte:


259

Type.GetType("namespace.qualified.TypeName") funziona solo quando il tipo si trova in mscorlib.dll o nell'assembly attualmente in esecuzione.

Se nessuna di queste cose è vera, avrai bisogno di un nome qualificato dall'assembly :

Type.GetType("namespace.qualified.TypeName, Assembly.Name")

3
il tipo esiste, si trova in una libreria di classi diversa e ho bisogno di ottenerlo per nome stringa
Omu

29
Invece di usare un nome qualificato dall'assembly, è possibile caricare l'assembly in base al nome - Assembly a = Assembly.Load("SomeLibrary");- e quindi caricare il tipo in base al nome dall'assembly - Type t = a.GetType("namespace.a.b.ClassName");.
Kenny Evitt

7
Forse potresti typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);risparmiare qualche problema, alla fine
Felype

La risposta di Felype è stata l'unica che ho potuto ottenere.
Rudy Scoggins

Aggiungi .FirstOrDefault () al commento di @Felype
Leandro

174

È anche possibile ottenere il tipo senza nome completo dell'assembly ma anche con il nome dll, ad esempio:

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

Ho avuto la stessa situazione e ha funzionato per me. Avevo bisogno di un oggetto di tipo "DataModel.QueueObject" e avevo un riferimento a "DataModel", quindi ho ottenuto il tipo come segue:

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

La seconda stringa dopo la virgola è il nome di riferimento (nome dll).


2
È un "trucco" o un metodo effettivo? Non riesco a trovarlo nella documentazione -_-. A proposito, finisce la mia sofferenza di 1 settimana! grazie
DnR

1
Questa è una soluzione molto più pulita, mi piacerebbe vedere se ci sono delle insidie ​​a causa di ciò.
cosacco

4
Il modulo utilizzato in questa risposta è anche un nome di tipo completo in base alla grammatica MSDN (quindi non è un trucco ). Il modulo è NamespaceTypeName, AssemblyNameSpecdove AssemblyNameSpecè l'identificatore dell'assembly senza proprietà. Anche se questa risposta è essenzialmente lo stesso del accettato presumo che alcune persone preferiscono questo perché fa via con alcuni dei "rumore" che le proprietà di assemblaggio introducono (ad esempio Version, Culture PublicKeyToken). Fortunatamente, le proprietà sono opzionali .
Martin Liversage

Per i tipi nidificati, potresti dover fare qualcosa del tipoAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo

Grazie, funziona per la cartella App_Code. Esempio: Type.GetType ("TypeName, App_Code");
Burak Koray Balcı

79

prova a usare questo metodo

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

Questo è ciò che effettivamente ha funzionato per me. Ho dovuto modificare aggiungendo una sottostringa trim prima del ciclo foreach, tuttavia, perché ho passato un nome qualificato dall'assembly e Assembly.GetType () funziona solo se escludi le informazioni sull'assembly.
Colin

sembra fantastico, ma per quanto riguarda i generici che utilizzano altri tipi di assembly?
Demetris Leptos

Non funziona per UWP perché AppDomainnon è supportato. Non sono sicuro di eventuali 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;
}

1
sembra fantastico, ma per quanto riguarda i generici che utilizzano altri tipi di assembly?
Demetris Leptos

1
@DemetrisLeptos (So che il commento è vecchio, ma altre persone potrebbero essere ancora interessate): usa int index = typeName.IndexOf ('`'); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } Notare che il Tdel tipo generico viene rimosso.
Bernhard Hiller

25

Se l'assembly fa parte della build di un'applicazione ASP.NET, è possibile utilizzare la classe BuildManager:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);

1
Questa è una risposta fantastica e dovrebbe essere più in alto nella pagina. Funziona come un fascino ed è semplicissimo rispetto al vecchio modo di ottenere il nome del tipo qualificato dell'assembly.
Graham

questo è sorprendentemente semplice e azzeccato, puoi aiutarmi con l'ottimizzazione delle prestazioni degli oggetti di riflessione?
Alok

@ Graham è vecchio ma è essenziale e non diventerà mai obsoleto o logicamente sbagliato. Ogni tipo è contenuto in un assembly specifico. Non possiamo identificare un tipo solo con il suo nome senza conoscere il suo contenitore. Sono possibili più tipi con lo stesso nome. Sebbene in qualche ambito specifico sappiamo per certo che un nome di tipo è univoco. Anche l'assemblea stessa ha bisogno di un nome forte (per essere garantito in modo univoco) in molti casi.
Hopeless

16

se la tua classe non è nell'assembly corrente devi dare qualificatoNome e questo codice mostra come ottenere il nome qualificato della classe

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

e quindi puoi ottenere il tipo con qualificatoNome

Type elementType = Type.GetType(qualifiedName);

8

Se è un tipo annidato, potresti dimenticare di trasformare un file. a un +

Indipendentemente da ciò, typeof( T).FullNameti dirò cosa dovresti dire

EDIT: BTW gli utilizzi (come sono sicuro che tu sappia) sono solo direttive per il compilatore in fase di compilazione e non possono quindi avere alcun impatto sul successo della chiamata API. (Se avessi riferimenti a progetti o assembly, ciò potrebbe potenzialmente avere influenza - quindi le informazioni non sono inutili, ci vuole solo un po 'di filtraggio ...)


Oh mio! Sai dove viene spiegata questa sintassi "+"?
Protettore uno

1
Protectorone L'ho imparato da amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC, ma è un po 'datato. Posso consigliare amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… come un libro infallibilmente utile per tutti gli sviluppatori .NET + include questo? La conclusione è che per i tipi, il CLR ha solo lo spazio dei nomi e il nome: un tipo annidato non è indirizzabile direttamente. Quindi un linguaggio, se ha un concetto di tipo annidato, può fare ciò di cui ha bisogno (anche se in generale la maggior parte dei lang usa un +separatore)
Ruben Bartelink

8

Poiché Type.GetType (String) necessita di Type.AssemblyQualifiedName , dovresti usare 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);

Version, Culture e PublicKeyToken non sono necessari per assemblyName questo motivo è possibile utilizzare MyAssembly.GetName (). Name.

Informazioni su Type.GetType (String) :

Se il tipo si trova nell'assembly attualmente in esecuzione o in Mscorlib.dll, è sufficiente fornire il nome del tipo qualificato dal suo spazio dei nomi.


6

Sto aprendo i controlli utente a seconda dei controlli utente a cui l'utente ha accesso specificato in un database. Quindi ho usato questo metodo per ottenere TypeName ...

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

Quindi ora è possibile utilizzare il valore restituito in strType per creare un'istanza di quell'oggetto.


riaprendo un argomento epico ... complimenti. Tuttavia devo downvote la tua risposta perché il TO conosce effettivamente il nome del tipo e vuole ottenere il tipo da esso. Btw .: quale metodo fai riferimento con <c> GetType (Namespace.ClassName) </c>, se è Type.GetType funzionerà solo sui tipi che si trovano all'interno dell'assembly in esecuzione corrente o mscorlib, ma come TO non dice nessuno di queste condizioni si applica.
HimBromBeere

2
@HimBromBeere Grazie per il voto negativo. Sono le persone come te che mi demotivano a pubblicare le mie scoperte. Sto ancora imparando lo sviluppo e sto solo cercando di aiutare gli altri. E ora ti aspetti che risponda alla tua domanda? A proposito, ho risposto correttamente alla domanda. La classe di cui stavo creando un'istanza risiede in un progetto diverso e per questo motivo è necessario utilizzare un nome AssemblyQualified. Quindi per favore leggi il resto dei commenti prima di votare. "il tipo esiste, è in una libreria di classi diversa e devo ottenerlo per nome stringa - Omu"
Stephan

6

Quando ho solo il nome della classe, lo uso:

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

4

Se si fa riferimento all'assembly e la classe è visibile:

typeof(namespace.a.b.ClassName)

GetType restituisce null perché il tipo non viene trovato, con typeof, il compilatore può aiutarti a scoprire l'errore.


il tipo esiste, è in una libreria di classi diversa e devo ottenerlo per nome stringa
Omu

4

Prova a utilizzare il nome completo del tipo che include le informazioni sull'assembly, ad esempio:

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

Ho avuto la stessa situazione quando stavo usando solo namesspace.classname per ottenere il tipo di una classe in un assembly diverso e non funzionava. Ha funzionato solo quando ho incluso le informazioni sull'assembly nella mia stringa di tipo come mostrato sopra.


3

Assicurati che la virgola sia subito dopo il nome completo

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

Poiché questo non funzionerà

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

Sono rimasto perplesso per alcuni giorni su questo


2

Per me, un "+" era la chiave! Questa è la mia classe (è annidata):

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

e questa riga di codice ha funzionato:

Type type = Type.GetType("PortalServices.PortalManagement+Merchant");

1

Questa soluzione sopra sembra essere la migliore per me, ma non ha funzionato per me, quindi l'ho fatto come segue:

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

Type myType = Type.GetType(typeAssemblyQualifiedName);

Il presupposto è che tu conosca il percorso dell'assemblea. Nel mio caso lo so perché questo è un assembly costruito da un altro progetto interno ed è incluso nella cartella bin del nostro progetto.

Nel caso in cui sia importante sto usando Visual Studio 2013, il mio target .NET è 4.0. Questo è un progetto ASP.NET, quindi ottengo il percorso assoluto tramite HttpContext. Tuttavia, il percorso assoluto non è un requisito come sembra da MSDN su AssemblyQualifiedNames


0

Ho barato. Poiché i tipi che voglio creare (per nome) sono tutti in una dll che controllo, ho semplicemente inserito un metodo statico nella dll nell'assembly che prende un nome semplice e chiama type.GetType da quel contesto e restituisce il risultato .

Lo scopo originale era che il tipo potesse essere specificato per nome nei dati di configurazione. Da allora ho cambiato il codice in modo che l'utente specificasse un formato da elaborare. Le classi del gestore del formato implementano un'interfaccia che determina se il tipo può analizzare il formato specificato. Quindi uso la reflection per trovare i tipi che implementano l'interfaccia e ne trovo uno che gestisce il formato. Quindi ora la configurazione specifica un nome di formato, non un tipo specifico. Il codice di riflessione può guardare le DLL adiacenti e caricarle, quindi ho un'architettura plug-in di tipo povero.


Ciao, ho perso il voto per errore, modifica la tua risposta così posso annullarla.
coloboxp
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.