Type.GetType (“space names.abClassName”) повертає null


216

Цей код:

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

повертає null.

і я маю в узінгах:

using namespace.a.b;

Оновлення:

Тип існує, він знаходиться в бібліотеці іншого класу, і мені потрібно отримати його за назвою рядка.


Дивіться цей stackoverflow.com/questions/441680/… для отримання інформації про те, як отримати ім'я кваліфікованої збірки.
Поліфун

Відповіді:


244

Type.GetType("namespace.qualified.TypeName") працює лише тоді, коли тип знайдений або в mscorlib.dll, або в даний час виконується збірка.

Якщо жодне з цих речей не відповідає дійсності, вам знадобиться ім'я, призначене для складання :

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

3
тип існує, він знаходиться в бібліотеці іншого класу, і мені потрібно отримати його за назвою рядка
Omu,

25
Замість використання імені, призначеного для складання, ви можете завантажити збірку за назвою - Assembly a = Assembly.Load("SomeLibrary");- і потім завантажити тип за назвою з збірки - Type t = a.GetType("namespace.a.b.ClassName");.
Кенні Евітт

6
Можливо, ви хотіли б typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);врятувати клопоту, зрештою
Феліпе

Відповідь Феліпе була єдиною, з якою я міг працювати.
Руді Скоггінс

Додайте .FirstOrDefault () до коментаря @Felype
Леандро

173

Ви також можете отримати тип без кваліфікованого імені, але також з іменем dll, наприклад:

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

У мене була така ж ситуація, і це працювало на мене. Мені знадобився об’єкт типу "DataModel.QueueObject" і мав посилання на "DataModel", тому я отримав тип таким чином:

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

Другий рядок після коми - це посилання (ім'я dll).


2
Це "фокус" чи фактичний метод? Я не можу знайти це в документації -_-. До речі, закінчується моя страждання на 1 тиждень! спасибі
ДНР

1
Це набагато чистіше рішення, я хотів би побачити, чи є якісь підводні камені через це.
козак

4
Форма, що використовується у цій відповіді, також є повністю кваліфікованою назвою типу відповідно до граматики MSDN (тому це не хитрість ). Форма - NamespaceTypeName, AssemblyNameSpecде AssemblyNameSpecідентифікатор збірки без будь-яких властивостей. Незважаючи на те, що ця відповідь по суті є такою ж, як і прийнята, я вважаю, що деякі люди віддають перевагу цьому, оскільки це усуває певний "шум", який вносяться властивості складання (наприклад Version, Culture PublicKeyToken). На щастя, властивості необов’язкові .
Мартін Ліверсайз

Для вкладених типів вам може знадобитися щось на кшталтAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo

Дякуємо, вона працює для папки App_Code. Приклад: Type.GetType ("TypeName, App_Code");
Burak Koray Balcı

79

спробуйте скористатися цим методом

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

Це те, що насправді працювало для мене. Мені довелося налаштувати додавання обрізки підрядки перед циклом foreach, однак я перейшов у відповідне ім'я, що відповідає кваліфікації збірки, а Assembly.GetType () працює лише у тому випадку, якщо ви виключаєте інформацію про складання.
Колін

це виглядає чудово, але як бути з дженериками, що використовують інші типи складання?
Деметрис Лептос

Не працює для UWP, оскільки AppDomainне підтримується. Не впевнений у будь-яких альтернативах.
Джеймс М

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
це виглядає чудово, але як бути з дженериками, що використовують інші типи складання?
Деметрис Лептос

1
@DemetrisLeptos (я знаю, що коментар старий - але інших людей все ще може зацікавити): використовуйте int index = typeName.IndexOf ('`'); if (індекс> 0) {typeName = _typeName.Substring (0, індекс + 2); } Зауважте, що Tзагальний тип знімається.
Бернхард Хіллер

25

Якщо збірка є частиною збірки програми ASP.NET, ви можете використовувати клас BuildManager:

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

1
Це фантастична відповідь і має бути вище на сторінці. Працює як шарм і просто мертво порівняно зі старим способом отримання імені кваліфікованого типу збірки.
Грем

це напрочуд просто і помітно, чи можете ви допомогти мені з оптимізацією продуктивності об'єктів відображення?
Алок

15

якщо ваш клас не є поточним, можливо, ви повинні надати кваліфіковане ім'я, і ​​цей код показує, як отримати кваліфіковане ім'я класу

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

і тоді ви можете набрати тип кваліфікованого імені

Type elementType = Type.GetType(qualifiedName);

8

Якщо це вкладений тип, можливо, ви забудете перетворити a. до +

Незалежно, typeof( T).FullName підкаже, що вам слід сказати

РЕДАКТУВАННЯ: До речі, ушивки (як я впевнений, ви знаєте) - це лише директиви для компілятора під час компіляції, і таким чином не можуть впливати на успіх виклику API. (Якщо у вас були посилання на проект чи збірку, це потенційно могло б вплинути - отже, інформація є марною, вона просто потребує деякої фільтрації ...)


О Боже! Чи знаєте ви, де пояснюється цей синтаксис "+"?
Захисник один

1
Протекторон Я дізнався про це з amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC, але це трохи застаріло. Чи можу я порекомендувати amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… як дуже корисну книгу для всіх .NET devs + включає це? Підсумок полягає в тому, що для типів CLR має лише простір імен та ім'я - вкладений тип не може бути адресований безпосередньо. Отже, мова, якщо вона має вкладений тип типу, робить те, що їй потрібно (хоча загалом більшість мов використовує +роздільник)
Рубен Бартелінк

6

Я відкриваю керування користувачами залежно від того, який користувач контролює, користувач має доступ до вказаних у базі даних. Тому я використав цей метод, щоб отримати TypeName ...

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

Отже, тепер можна використовувати значення, повернене в strType, для створення примірника цього об'єкта.


повторне відкриття епічної старої теми ... поздоровлення. Однак я повинен спростувати вашу відповідь, оскільки TO насправді знає Typename і хоче отримати тип від нього. Btw .: на який метод ви посилаєтесь <c> GetType (Namespace.ClassName) </c>, якщо його Type.GetType, він працюватиме лише на типи, що знаходяться в поточній збірній або mscorlib, але як TO не має жодного цих умов застосовується.
HimBromBeere

2
@HimBromBeere Дякую за голос "за" Такі люди, як ви, мотивують мене публікувати свої висновки. Я все ще навчаюся розвитку, і я просто намагаюся допомагати іншим. А тепер ви очікуєте, що я відповім на ваше запитання? До речі, я правильно відповів на питання. Клас, з якого я створював екземпляр, перебуває в іншому проекті, і для цього треба використовувати ім'я AssemblyQualified. Тож, будь ласка, прочитайте решту коментарів перед тим, як звернути увагу. "тип існує, він знаходиться в бібліотеці іншого класу, і мені потрібно отримати його за назвою рядка - Omu"
Stephan

6

Коли у мене є лише назва класу, я використовую це:

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

5

Як Type.GetType (String) потрібен Type.AssemblyQualifiedName, ви повинні використовувати 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);

Версія, культура та PublicKeyToken не потрібні assemblyName , тому ви можете використовувати MyAssembly.GetName ().

Про Type.GetType (String) :

Якщо тип знаходиться у виконаній в даний час збірці або в Mscorlib.dll, достатньо вказати ім'я типу, кваліфіковане за його простором імен.


4

Якщо збірка посилається і Клас видимий:

typeof(namespace.a.b.ClassName)

GetType повертає null, оскільки тип не знайдений, за допомогою typeof компілятор може допомогти вам з’ясувати помилку.


тип існує, він знаходиться в бібліотеці іншого класу, і мені потрібно отримати його за назвою рядка
Omu,

4

Спробуйте використовувати повне ім'я типу, яке містить інформацію про збірку, наприклад:

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

У мене була така ж ситуація, коли я використовував тільки ім'я namesspace.class, щоб отримати тип класу в іншій збірці, і це не працюватиме. Працює лише тоді, коли я включив інформацію про збірку в рядок типу, як показано вище.


3

Переконайтеся, що кома знаходиться безпосередньо після повністю кваліфікованого імені

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

Як це не буде працювати

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

Мене кілька днів тупотували на цьому


2

Для мене ключовим було "+"! Це мій клас (це вкладений):

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

і цей рядок коду працював:

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

1

Це рішення, здається, найкраще для мене, але воно не спрацювало для мене, тому я зробив це так:

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

Type myType = Type.GetType(typeAssemblyQualifiedName);

Передумовою є те, що ви знаєте шлях складання. У моєму випадку я це знаю, тому що це збірка, побудована з іншого внутрішнього проекту та включена до папки бін нашого проекту.

У випадку, якщо це має значення, я використовую Visual Studio 2013, цільовим .NET є 4.0. Це проект ASP.NET, тому я отримую абсолютний шлях через HttpContext. Однак абсолютний шлях не є вимогою, як це здається з MSDN на AssemblyQualifiedNames


0

Я обдурив. Оскільки типи, які я хочу створити (по імені), знаходяться в контролі dll, я просто поміщаю статичний метод у dll в зборі, який приймає просте ім’я, і виклику type.GetType з цього контексту і повертає результат .

Початкова мета полягала в тому, щоб тип міг бути вказаний іменем у даних конфігурації. З тих пір я змінив код, щоб користувач вказав формат для обробки. Класи обробників форматів реалізують інтерфейс, який визначає, чи може тип розбору заданого формату. Потім я використовую відображення для пошуку типів, що реалізують інтерфейс, і знаходжу такий, який обробляє формат. Тож тепер конфігурація вказує назву формату, а не конкретний тип. Код відображення може переглядати сусідні клітини та завантажувати їх, тож у мене є своєрідна архітектура плагінів для бідних людей.


Привіт, я спростував помилку, відредагуйте свою відповідь, щоб я міг її скасувати.
coloboxp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.