Подтвердить что ты не робот

Как работает Type.GetType, когда вы получаете частично квалифицированное имя типа?

Во многих местах я встречаю частично квалифицированные имена типов формы FullTypeName, AssemblyName, то есть как Type.AssemblyQualifiedName, только без квалификаторов версии, культуры и publicKeyToken.

Мой вопрос в том, как можно преобразовать его в соответствующий Type в минимальные усилия? Я думал, что Type.GetType выполняет эту работу, но, увы, это не так. Следующий код, например, возвращает null:

Type.GetType("System.Net.Sockets.SocketException, System");

Конечно, если я укажу полное имя, оно действительно работает:

Type.GetType("System.Net.Sockets.SocketException, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

Большое спасибо.

4b9b3361

Ответ 1

Если DLL файл в нем еще не загружен в домен приложения (например, вы его использовали), вам нужен полный путь, как этот, если он уже загружен, он может найти его с более короткой версией.

Чтобы ответить на ваш вопрос: вторая версия всегда работает, придерживайтесь ее, и у вас есть один способ беспокоиться.

Ответ 2

Если сборка была загружена в текущий домен, тогда обычно работает код ниже:

public static Type GetTypeEx(string fullTypeName)
{
    return Type.GetType(fullTypeName) ??
           AppDomain.CurrentDomain.GetAssemblies()
                    .Select(a => a.GetType(fullTypeName))
                    .FirstOrDefault(t => t != null);
}

Вы можете использовать его так:

Type t = GetTypeEx("System.Net.Sockets.SocketException");

Ответ 3

Код, работающий с короткой формой:

    Assembly a = Assembly.LoadWithPartialName(assemblyName);
    Type t = a.GetType(typeName);

но LoadWithPartialName устарело, поэтому я думаю, вы должны придерживаться длинной формы.

Ответ 4

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

Согласно документации, Type.GetType(строка) требует AssemblyQualifiedName, если только этот тип не находится в выполняющейся в настоящее время сборке или в mscorlib, и в этом случае требуется имя типа с именем пространства имен.

Обратите внимание, что AssemblyQualifiedName включает полное DisplayName сборки типа (с ключом версии, культуры и открытого ключа).

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

Ответ 5

Правда, Type.GetType(string) действительно требует AssemblyCualifiedName. Это может быть во многих формах:

MyNS.MyType, MyAssembly, Version=x.x.x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX

Также допустимы следующие: AssemblyQualifiedNames:

MyNS.MyType, MyAssembly, Version=x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX
MyNS.MyType, MyAssembly, Culture=xxx, PublicKeyToken=XXXXXXXXXX
MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX
MyNS.MyType, MyAssembly

Для подписанной сборки минимальный размер, необходимый для FullyQualifiedAssemblyName:

MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX

Для неподписанной сборки минимальный размер, необходимый для FullyQualifiedAssemblyName:

MyNS.MyType, MyAssembly

Не нужно, чтобы все "ручные махания" выполнялись в фрагментах кода, предоставленных другими пользователями. Убедитесь, что ваши имена типов настроены правильно, и вы можете получить доступ к своим типам (и загружать сборки динамически) с высокой степенью гибкости. Я делаю это регулярно.

В примере OP с использованием:

Type.GetType("System.Net.Sockets.SocketException, System")

Причиной отказа было отсутствие PublicKeyToken. Все сборки .Net FW подписаны и, следовательно, требуют, чтобы PublicKeyToken разрешил имя Ассамблеи. Было бы выполнено следующее:

Type.GetType("System.Net.Sockets.SocketException, System, PublicKeyToken=b77a5c561934e089")