Поделиться через


Методы "System.Type.GetType"

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean, Boolean) Используйте перегрузку метода и связанные с ней перегрузки (GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>)иGetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean)) для замены реализации GetType метода по умолчанию более гибкими реализациями. Предоставляя собственные методы, разрешающие имена типов и имена сборок, содержащих их, можно выполнить следующие действия:

  • Управляйте тем, из какой версии сборки загружается тип.
  • Укажите другое место, где можно искать имя типа, не включающее имя сборки.
  • Загрузка сборок с использованием частичных имен сборок.
  • Возвращает подклассы System.Type , которые не создаются средой CLR.

Например, в устойчивой к версиям сериализации этот метод позволяет искать наиболее подходящую сборку с помощью частичного имени. Для других перегрузок GetType метода требуется имя типа с указанием сборки, включающее номер версии.

Альтернативные реализации системы типов могут потребовать возврата подклассов System.Type, не создаваемых CLR; все типы, возвращаемые другими перегрузками метода GetType, — это типы времени выполнения.

Заметки об использовании

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

Примечание.

Если вы не знакомы с понятием имен типов с указанием сборки, ознакомьтесь со свойством AssemblyQualifiedName .

Если typeName не является сборочно-квалифицированным именем, разрешение сборки пропускается. Неквалифицированные имена типов можно разрешить в контексте mscorlib.dll/System.Private.CoreLib.dll или текущей выполняемой сборки или при необходимости предоставить сборку в параметре typeResolver . Эффекты включения или исключения имени сборки для различных типов разрешения имен отображаются в виде таблицы в разделе разрешения смешанных имен .

Общие заметки об использовании:

  • Не передавайте методы в assemblyResolver или typeResolver, если они поступают от неизвестных или ненадёжных вызывающих объектов. Используйте только те методы, которые вы предоставляете или с которыми вы знакомы.

    Осторожность

    Использование методов из неизвестных или недоверенных вызывающих объектов может привести к повышению привилегий для вредоносного кода.

  • Если опущены assemblyResolver параметры и/или typeResolver параметры, значение throwOnError параметра передается методам, выполняющим разрешение по умолчанию.

  • Если throwOnError это trueтак, этот метод создает TypeLoadException исключение, когда typeResolver возвращается null, и FileNotFoundException когда assemblyResolver возвращается null.

  • Этот метод не перехватывает исключения, вызванные assemblyResolver и typeResolver. Вы несете ответственность за все исключения, создаваемые методами резольвера.

Разрешение сборок

Метод assemblyResolver получает объект AssemblyName, который создается путем разбора имени строковой сборки, которая содержится в typeName. Если имя сборки не содержится в typeName, assemblyResolver не вызывается, а null передается в typeResolver.

Если assemblyResolver не указан, для поиска сборки используется стандартная проверка сборки. Если указан assemblyResolver, метод не выполняет стандартную проверку; в этом случае необходимо убедиться, что assemblyResolver может обработать все сборки, которые вы ему передаете.

Метод assemblyResolver должен возвращать null, если сборка не может быть разрешена. Если assemblyResolver возвращаетсяnull, typeResolver не вызывается и не выполняется дальнейшая обработка; кроме того, при FileNotFoundExceptionthrowOnErrortrueналичии возникает исключение.

Если переданное в assemblyResolverAssemblyName является частичным именем, одна или несколько его частей - null. Например, если у него нет версии, Version свойство имеет значение null. Если свойство Version, свойство CultureInfo и метод GetPublicKeyToken возвращают null, то было предоставлено только простое имя сборки. Метод assemblyResolver может использовать или игнорировать все части имени сборки.

Эффекты различных параметров разрешения сборок отображаются в виде таблицы в разделе "Разрешение смешанных имен " для простых и сборочных имен.

Разрешение типов

Если имя сборки для typeName не указано, typeResolver всегда вызывается. Если typeName указывает имя сборки, typeResolver вызывается только при успешном разрешении имени сборки. Если assemblyResolver или стандартная проверка сборок дает результат null, typeResolver не вызывается.

Метод typeResolver получает три аргумента:

  • Сборка для поиска или null, если typeName не содержит имени сборки.
  • Простое имя типа. В случае вложенного типа это самый внешний содержащий тип. В случае универсального типа это простое имя универсального типа.
  • Логическое значение, указывающее true , следует ли игнорировать регистр имен типов.

Реализация определяет способ использования этих аргументов. Метод должен возвращать typeResolvernull, если он не может разрешить тип. Если typeResolver возвращается null и throwOnError является true, эта перегрузка GetType вызывает TypeLoadExceptionисключение.

Эффекты различных параметров разрешения типов отображаются в виде таблицы в разделе "Разрешение смешанных имен " для простых и сборочных имен.

Разрешение вложенных типов

Если typeName является вложенным типом, typeResolver передается только имя внешнего содержащего типа. Когда typeResolver возвращает этот тип, метод GetNestedType вызывается рекурсивно, пока не будет разрешен внутренний вложенный тип.

Разрешение универсальных типов

Элемент GetType вызывается рекурсивно для разрешения универсальных типов: сначала для разрешения самого универсального типа, а затем для разрешения аргументов типа. Если аргумент типа является универсальным, GetType вызывается рекурсивно для разрешения его аргументов типа и т. д.

Сочетание assemblyResolver и typeResolver, которое вы предоставляете, должно быть способно разрешать все уровни этой рекурсии. Например, предположим, что вы предоставляете assemblyResolver, который управляет загрузкой MyAssembly. Предположим, вы хотите разрешить универсальный тип Dictionary<string, MyType> (Dictionary(Of String, MyType) в Visual Basic). Можно передать следующее имя универсального типа:

"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"

Обратите внимание, что MyType является единственным аргументом типа, квалифицированным сборкой. Имена классов Dictionary<TKey,TValue> и String не имеют квалификации сборки. Ваш typeResolver должен иметь возможность обрабатывать либо сборку, либо null, потому что он будет получать null для Dictionary<TKey,TValue> и String. Он может обработать этот случай путем вызова перегрузки метода, принимающего GetType строку, так как оба имена неквалифицированных типов находятся в mscorlib.dll/System.Private.CoreLib.dll:

Type t = Type.GetType(test,
                      (aName) => aName.Name == "MyAssembly" ?
                          Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : null,
                      (assem, name, ignore) => assem == null ?
                          Type.GetType(name, false, ignore) :
                              assem.GetType(name, false, ignore)
                     );
let t =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else null),
        fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr))

Метод assemblyResolver не вызывается для типа словаря и типа строки, так как эти имена типов не квалифицированы сборкой.

Теперь предположим, что вместо System.String, первый универсальный тип аргумента — это YourType, из YourAssembly.

"System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]"

Так как эта сборка не является ни mscorlib.dll/System.Private.CoreLib.dll, ни текущей выполняемой сборкой, невозможно разрешить YourType без имени, указанного в сборке. Так как ваш assemblyResolve вызов будет вызываться рекурсивно, он должен иметь возможность обрабатывать этот случай. Вместо возврата null для сборок, отличных от MyAssembly, теперь выполняется загрузка сборки с использованием предоставленного объекта AssemblyName.

Type t2 = Type.GetType(test,
                       (aName) => aName.Name == "MyAssembly" ?
                           Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") :
                           Assembly.Load(aName),
                       (assem, name, ignore) => assem == null ?
                           Type.GetType(name, false, ignore) :
                               assem.GetType(name, false, ignore), true
                      );
let t2 =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else Assembly.Load aName),
        (fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr)), true)

Устранение неоднозначности в именах типов, содержащих специальные символы

Некоторые символы имеют особые значения в именах с указанием сборки. Если имя простого типа содержит эти символы, символы вызывают ошибки синтаксического анализа, если простое имя является частью имени, заданного сборкой. Чтобы избежать ошибок синтаксического анализа, перед передачей полного имени сборки в метод GetType, необходимо экранировать специальные символы с помощью обратной косой черты. Например, если тип называется Strange]Type, служебный символ должен быть добавлен перед квадратной скобкой следующим образом: Strange\]Type.

Примечание.

Имена с такими специальными символами не могут быть созданы в Visual Basic или C#, но можно создавать с помощью общего промежуточного языка (CIL) или путем создания динамических сборок.

В следующей таблице показаны специальные символы для имен типов.

Персонаж Значение
, (запятая) Разделитель имен с указанием сборки.
[] (квадратные скобки) Как пара суффиксов указывает тип массива; как пара разделителей заключает универсальные списки аргументов и имена с указанием сборки.
& (амперсанд) Как суффикс указывает, что тип является ссылочным типом.
* (звездочка) Как суффикс указывает, что тип является типом указателя.
+ (плюс) Разделитель для вложенных типов.
\ (обратная косая черта) Escape-символ.

Такие свойства, как AssemblyQualifiedName, возвращают правильно экранированные строки. Необходимо правильно передать в метод экранированные строки GetType . В свою очередь, метод GetType правильно передает экранированные имена в typeResolver и в методы разрешения типов по умолчанию. Если вам нужно сравнить имя с незакрытым именем typeResolver, необходимо удалить escape-символы.

Разрешение смешанных имен

В следующей таблице приведены сведения о взаимодействии между assemblyResolver, typeResolver и разрешением имен по умолчанию для всех сочетаний имени типа и имени сборки в typeName.

Содержимое имени типа Метод сопоставителя сборок Метод сопоставителя типов Результат
тип, сборка null null Эквивалентно вызову метода перегрузки Type.GetType(String, Boolean, Boolean).
тип, сборка предоставленный null assemblyResolver возвращает сборку, или null, если не удается разрешить сборку. Если сборка разрешена, перегрузка метода Assembly.GetType(String, Boolean, Boolean) используется для загрузки типа из сборки; в противном случае попытка разрешить тип не предпринимается.
тип, сборка null предоставленный Эквивалентно преобразованию имени сборки в объект AssemblyName и вызову перегруженного метода Assembly.Load(AssemblyName) для получения сборки. Если сборка разрешена, она передается в typeResolver; в противном случае она не вызывается, и не предпринимается дальнейших попыток разрешения типа в typeResolver.
тип, сборка предоставленный предоставленный assemblyResolver возвращает сборку, или возвращает null, если не может разрешить сборку. Если сборка разрешена, она передается в typeResolver; в противном случае typeResolver не вызывается, и не предпринимается дальнейших попыток разрешения типа.
тип null, предоставлено null Эквивалентно вызову метода Type.GetType(String, Boolean, Boolean) с перегрузкой. Поскольку имя сборки не указано, выполняется поиск только для mscorlib.dll/System.Private.CoreLib.dll и текущей выполняемой сборки. Если assemblyResolver указан, он игнорируется.
тип null, предоставленный предоставленный typeResolver вызывается и null передается для сборки. typeResolver может предоставить тип из любой сборки, включая сборки, которые он загружает с этой целью. Если assemblyResolver указан, он игнорируется.
сборка null, предоставленный null, предоставлено Создается исключение FileLoadException, потому что имя сборки анализируется так, как если бы это было имя типа с полным указанием сборки. Это приводит к недопустимому имени сборки.