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

Этот код:

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

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

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

using namespace.a.b;

Обновить:

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

18 ответов

Решение

Type.GetType("namespace.qualified.TypeName") работает только тогда, когда тип найден либо в mscorlib.dll, либо в текущей выполняемой сборке.

Если ни одна из этих вещей не является правдой, вам понадобится полное имя сборки.

Вы также можете получить тип без имени сборки, но также с именем dll, например:

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

У меня была такая же ситуация, и она работала на меня. Мне был нужен объект типа "DataModel.QueueObject" и имел ссылку на "DataModel", поэтому я получил тип следующим образом:

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

Вторая строка после запятой - это имя ссылки (имя dll).

Попробуйте использовать этот метод

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

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

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
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;
}

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

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

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

Type elementType = Type.GetType(qualifiedName);

Поскольку 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);

В качестве AssemblyName вам не нужно FullName, требуется только имя без Version, Culture и PublicKeyToken.

Когда у меня есть только имя класса, я использую это:

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

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

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

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

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

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

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

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

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

У меня была такая же ситуация, когда я использовал только namesspace.classname, чтобы получить тип класса в другой сборке, и это не сработало. Работал только тогда, когда я включил информацию о сборке в строку типа, как показано выше.

Если на сборку ссылаются и класс виден:

typeof(namespace.a.b.ClassName)

GetType возвращает null, потому что тип не найден, с помощью typeof компилятор может помочь вам обнаружить ошибку.

Убедитесь, что запятая находится сразу после полного имени

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

Как это не получится

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

Я был в тупике на несколько дней на этом

Для меня "+" был ключом! Это мой класс (он вложенный):

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

и эта строка кода работает:

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

Вот что сработало для меня: я не хотел создавать длинные имена библиотек и не хотел загружать библиотеки вручную, поэтому вместо этого я нашел библиотеку программно. По сути, я использую короткое имя для поиска совпадения в GetTypes(), а затем использую эту найденную конструкцию для доступа к длинному имени в сборке. Мне очень понравилась реализация LINQ от Марчино, описанная выше, и я хотел, чтобы она работала и у меня, но я недостаточно хорош, чтобы работать с двумя переменными в инструкции LINQ :-)

          public static Type GetType(string type)
    {
        Type t = null;
        foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
        {
            foreach (var s in a.GetTypes())
            {
                if (s.Name == type)
                {
                    t = a.GetType(s.FullName); 
                    if (t != null) return t;
                }
            }
        }

        return t;
    }

Это решение, представленное выше, кажется мне лучшим, но оно не сработало для меня, поэтому я сделал это следующим образом:

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

Очень поздний ответ, но если кто-то имеет дело с этим десятилетие спустя:

Существует очень, очень маленькая вероятность того, что ваш класс в Visual Studio имеетBuild Actionустановлен в "Content" вместо "Compile".

Щелкните свой класс в обозревателе решений, затем просмотрите свойства.

Убедитесь, что действие сборки — «Скомпилировать», а не «Содержимое».

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

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

Другие вопросы по тегам