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