Как получить тип из сборки, загруженной из другой папки? - PullRequest
7 голосов
/ 04 ноября 2011

Я использую следующий код:

Assembly.LoadFile("the assembly in another folder");
var type = Type.GetType("the full name of the type");

Даже если сборка уже была загружена до этой строки кода, она всегда возвращает ноль в type.

PS: я сделалпередайте полное имя сборки, включая пространство имен, имя типа, имя сборки, версию и общедоступный токен.

Ответы [ 4 ]

9 голосов
/ 04 ноября 2011

Type.GetType ищет только типы в вызывающей сборке и типы в mscorlib.dll, если только вы не передаете имя типа, определенное сборкой. Смотри здесь.

EDIT

Похоже, что Type.GetType может извлекать Type экземпляры только из сборок в контексте загрузки. Сборки, загруженные с использованием LoadFile, находятся в без контекста , а сборки, загруженные с использованием LoadFrom, находятся в контексте загрузки из; ни один из этих контекстов не позволяет использовать Type.GetType, поэтому разрешение не будет выполнено. Эта статья показывает, что Type информация может быть получена для Assembly, когда каталог, в котором она находится, добавляется в качестве проверяющего privatePath, так как он затем окажется в контексте загрузки, но завершится ошибкой в ​​других контекстах .

4 голосов
/ 09 апреля 2012

«Правильный» (рекомендуемый MS) способ сделать это, когда необходимо использовать Type.GetType(string) для типов в сборках, которые находятся не в контексте загрузки, а в контексте загрузки или без контекста, заключается в привязке ксобытие Appdomain.AssemblyResolve.Следующий код относительно эффективен:

// this resolver works as long as the assembly is already loaded
// with LoadFile/LoadFrom or Load(string) / Load(byte[])
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
    var asm = (from a in AppDomain.CurrentDomain.GetAssemblies()
              where a.GetName().FullName == args.Name
              select a).FirstOrDefault();

    if(asm == null)
         throw FileNotFoundException(args.Name);     // this becomes inner exc

    return asm;
}

// place this somewhere in the beginning of your app:
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;

Представляется несколько более эффективным создать комбинацию событий AssemblyLoad / Resolve, чтобы сохранить словарь загруженных сборок (используйте имя сборки в качестве ключа).

On Assembly.LoadFile
Существует несколько серьезных недостатков при использовании этого метода. Согласно MSDN :

LoadFile не загружает файлы в контекст LoadFrom и не разрешает зависимости, используя путь загрузки, как это делает метод LoadFrom.

Поэтому, если возможно, не используйте LoadFile.Результирующая сборка загружается в контексте без контекста, который имеет еще больше недостатков, чем контекст загрузки из.Вместо этого используйте Assembly.LoadFrom , и зависимости будут автоматически загружаться из пути загрузки.

2 голосов
/ 04 ноября 2011

Самый простой способ сделать это - просто перехватить возвращаемое значение Assembly.LoadFile в переменной и вызвать GetType для него следующим образом:

Assembly assem = Assembly.LoadFile("assemblyLocation");
assem.GetType("typeName");

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

1 голос
/ 04 ноября 2011

вы можете попробовать это ....

Assembly.GetAssembly предполагает, что у вас есть экземпляр типа, а Type.GetType предполагает, что у вас есть полное имя типа, которое включает имя сборки.

Вы можете указать путь, по которому расположена сборка .....

Если у вас есть только имя базового типа, вам нужно сделать что-то более похожее на это:

public static String GetAssemblyNameContainingType(String typeName) 
{
    foreach (Assembly currentassembly in AppDomain.CurrentDomain.GetAssemblies()) 
    {
        Type t = currentassembly.GetType(typeName, false, true);
        if (t != null) {return currentassembly.FullName;}
    }

    return "not found";
}

Это также предполагает, что ваш тип объявлен в корне. Вам нужно будет указать пространство имен или включающие типы в имени или выполнить итерацию таким же образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...