Type.GetType («namespace.abClassName») возвращает ноль


216

Этот код:

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

возвращается null .

и я имею в употреблениях:

using namespace.a.b;

Обновить:

Тип существует, он находится в другой библиотеке классов, и мне нужно получить его по строковому имени.


См. Этот stackoverflow.com/questions/441680/… для получения информации о том, как получить квалифицированное имя сборки.
Polyfun

Ответы:


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");.
Кенни Эвитт

7
Возможно, вы могли бы, typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);возможно, сэкономить некоторые хлопоты, в конце концов
Felype

Ответ Фелипе был единственным, на что я мог получить работу.
Руди Скоггинс

Добавьте .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");
Бурак Корай Балчи

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 (я знаю, что комментарий старый, но другие могут все еще интересоваться): use int index = typeName.IndexOf ('`'); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } Обратите внимание, что Tуниверсальный тип удален.
Бернхард Хиллер

25

Если сборка является частью сборки приложения ASP.NET, вы можете использовать класс BuildManager:

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

1
Это фантастический ответ и должен быть выше на странице. Работает как шарм и очень прост по сравнению со старым способом получения квалифицированного имени типа сборки.
Грэм

это удивительно просто и понятно, можете ли вы помочь мне с оптимизацией производительности объектов отражения?
Alok

15

если ваш класс не находится в текущей сборке, вы должны дать qualName, и этот код показывает, как получить квалифицированное имя класса

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

и тогда вы можете получить тип с qualName

Type elementType = Type.GetType(qualifiedName);

8

Если это вложенный тип, вы можете забыть преобразовать. к +

Несмотря на, typeof( T).FullName скажу вам, что вы должны сказать

РЕДАКТИРОВАТЬ: Кстати, использование (как я уверен, вы знаете) являются только директивами для компилятора во время компиляции и, таким образом, не может иметь никакого влияния на успех вызова API. (Если у вас есть ссылки на проект или сборку, это потенциально может оказать влияние - следовательно, информация не бесполезна, она просто требует некоторой фильтрации ...)


Боже мой! Вы знаете, где объясняется этот синтаксис "+"?
Один защитник

1
Protectorone Я узнал об этом на amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC, но это немного устарело. Могу ли я рекомендовать amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… как безошибочно полезная книга для всех разработчиков .NET +, включает это? Суть в том, что для типов CLR имеет только пространство имен и имя - вложенный тип не имеет прямой адресации. Следовательно, язык, если он имеет концепцию вложенного типа, выполняет то, что ему нужно (хотя в большинстве языков используется +разделитель)
Ruben Bartelink

6

Я открываю пользовательские элементы управления в зависимости от того, какие пользовательские элементы управления имеют доступ к пользователю, указанному в базе данных. Поэтому я использовал этот метод, чтобы получить TypeName ...

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

Так что теперь можно использовать значение, возвращаемое в strType, чтобы создать экземпляр этого объекта.


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

2
@HimBromBeere Спасибо за отрицательное голосование. Именно такие люди, как ты, демотивируют меня, чтобы опубликовать мои выводы. Я все еще учусь развитию, и я просто пытаюсь помочь другим. А теперь вы ожидаете, что я отвечу на ваш вопрос? Кстати, я правильно ответил на вопрос. Класс, в котором я создавал экземпляр, находится в другом проекте, и из-за этого нужно использовать имя AssemblyQualified. Поэтому, пожалуйста, прочитайте оставшиеся комментарии перед тем, как понизить голосование. «тип существует, он находится в другой библиотеке классов, и мне нужно получить его по строковому имени - Omu»
Стефан

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

Version, Culture и PublicKeyToken не требуются assemblyName, поэтому вы можете использовать MyAssembly.GetName (). Name.

О 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.classname, чтобы получить тип класса в другой сборке, и это не сработало. Работал только тогда, когда я включил информацию о сборке в строку типа, как показано выше.


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

Предварительным условием является то, что вы знаете путь сборки. В моем случае я знаю это, потому что это сборка, созданная из другого внутреннего проекта и включенная в папку bin нашего проекта.

На случай, если я использую Visual Studio 2013, моя цель .NET - 4.0. Это проект ASP.NET, поэтому я получаю абсолютный путь через HttpContext. Однако абсолютный путь не является обязательным, как это видно из MSDN на AssemblyQualifiedNames


0

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

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


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