Разница между LoadFile и LoadFrom со сборками.NET?
Я смотрел на документацию MSDN и я все еще немного запутался в том, что именно разница между использованием LoadFile
а также LoadFrom
при загрузке сборки. Может кто-нибудь привести пример или аналогию, чтобы лучше описать это. Документация MSDN смутила меня больше. Также является ReflectionOnlyLoadFrom
такой же как LoadFrom
за исключением того, что он загружает сборку только в режиме отражения.
Так как мой опыт работы с.NET не самый лучший, вот несколько вопросов относительно документации MSDN с использованием LoadFile:
1) Что это значит LoadFile
исследует сборки, которые имеют одинаковую идентичность, но расположены по разным путям? Что такое личность (пример)?
2) Это заявляет LoadFile
не загружает файлы в "LoadFrom Context" и не разрешает зависимости, используя путь загрузки. Что это значит, может кто-нибудь привести пример?
3) Наконец, говорится, что LoadFile
полезен в этом ограниченном сценарии, потому что LoadFrom не может загружать сборки, которые имеют одинаковые идентификаторы, но разные пути; он будет загружать только первую такую сборку, что снова подводит меня к тому же вопросу, какова идентичность сборок?
8 ответов
Это проясняет?
// path1 and path2 point to different copies of the same assembly on disk:
Assembly assembly1 = Assembly.LoadFrom(path1);
Assembly assembly2 = Assembly.LoadFrom(path2);
// These both point to the assembly from path1, so this is true
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);
assembly1 = Assembly.LoadFile(path1);
assembly2 = Assembly.LoadFile(path2);
// These point to different assemblies now, so this is false
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);
Изменить: чтобы ответить на вопросы, которые вы подняли в своем пересмотренном вопросе, вы определенно хотите прочитать Сюзанну Кук об идентичности сборки.
Существует множество правил, управляющих загрузкой сборок, и некоторые из них связаны с разрешением зависимостей - если ваша AssemblyA зависит от AssemblyB, где.NET должен искать AssemblyB? В глобальном кэше сборок, тот же каталог, который он нашел AssemblyA, или где-то еще целиком? Кроме того, если он находит несколько копий этой сборки, как ему выбрать, какую из них использовать?
LoadFrom
имеет один набор правил, в то время как LoadFile
имеет другой набор правил. Трудно представить много причин для использования LoadFile
, но если вам нужно было использовать отражение на разных копиях одной и той же сборки, это для вас.
LoadFile против LoadFrom
Будьте осторожны - это не одно и то же.
LoadFrom() проходит через Fusion и может быть перенаправлен на другую сборку по другому пути, но с тем же идентификатором, если он уже загружен в контексте LoadFrom.
LoadFile() не связывается через Fusion вообще - загрузчик просто идет вперед и загружает ровно * то, что запросил вызывающий. Он не использует ни контекст Load, ни LoadFrom.
Итак, LoadFrom() обычно дает вам то, что вы просили, но не обязательно. LoadFile() предназначен для тех, кто действительно, действительно хочет именно то, что запрашивается. (* Однако, начиная с v2, политика будет применяться как к LoadFrom(), так и к LoadFile(), поэтому LoadFile() не обязательно будет именно тем, что было запрошено. Кроме того, начиная с v2, если сборка с идентификатором находится в GAC, вместо этого будет использоваться копия GAC. Используйте ReflectionOnlyLoadFrom(), чтобы загрузить именно то, что вам нужно, но обратите внимание, что сборки, загруженные таким образом, не могут быть выполнены.)
LoadFile() имеет подвох. Поскольку он не использует контекст привязки, его зависимости не обнаруживаются автоматически в его каталоге. Если они недоступны в контексте загрузки, вам необходимо подписаться на событие AssemblyResolve, чтобы связать их с ними.
Смотрите здесь.
Также см. Статью " Выбор обязательного контекста" в том же блоге.
После большого количества царапин на голове я обнаружил разницу сам этим днем.
Я хотел загрузить DLL во время выполнения, и DLL находилась в другом каталоге. Эта DLL имеет свои собственные зависимости (DLL), которые также находятся в том же каталоге.
LoadFile (): загружает конкретную DLL, но не зависимости. Поэтому, когда первый вызов был сделан из библиотеки DLL в одну из этих других библиотек DLL, он вызвал исключение FileNotFoundException.
LoadFrom (): загрузил указанную мной DLL, а также все зависимости, которые находились в этом каталоге.
Я заметил одно отличие:
Assembly.LoadFile - Загружает сборку в другом домене приложений с ограниченными правами пользователя (diffrence principel). такие операции, как серилизация / десерилизация, не могут быть выполнены.
Assembly.LoadFrom- загружает сборку в одном домене приложений с теми же правами пользователя (тот же принцип).
Примечание. Если одна сборка загружается по пути 8.3, а затем по пути, отличному от 8.3, они будут рассматриваться как разные сборки, даже если они являются одной и той же физической DLL.
.NET имеет другой контекст загрузки. Сюзанна Кук написала о них здесь: http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx
Так Карантин.Net не перепутывает ссылки.
В моем случае мне просто нужно было просто удалить кеш приложения ASP, расположенный @ C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files
, Он перестраивается при первом запуске сайта. Обязательно сначала остановите IIS.
Надеюсь, что это поможет кому-то, как он сделал для меня.
Согласно документации:
LoadFile (String): загружает содержимое файла сборки с указанием пути к файлу.
LoadFrom (String): загружает сборку по ее имени файла или пути.