2009-09-25 3 views
98

Я смотрел документацию msdn, и я все еще немного смущен тем, что именно представляет собой различие между использованием LoadFile и LoadFrom при загрузке сборки. Может ли кто-нибудь представить пример или аналогию, чтобы лучше описать его. Документация MSDN смутила меня больше. Кроме того, Is ReflectionOnlyLoadFrom совпадает с LoadFrom, за исключением того, что он загружает сборку только в режиме отражения.Разница между LoadFile и LoadFrom с .NET Assemblies?

Поскольку мой опыт .NET не самый большой, вот некоторые вопросы, касающиеся документации MSDN с помощью LoadFile:

1) Что значит по LoadFile исследует узлы, которые имеют ту же идентичность, но расположены в разных пути? Что такое личность (пример)?

2) В нем указано, что LoadFile не загружает файлы в «контекст LoadFrom» и не разрешает зависимости с использованием пути загрузки. Что это значит, может ли кто-нибудь привести пример?

3) Наконец, в нем говорится, что LoadFile полезен в этом ограниченном сценарии, поскольку LoadFrom не может загружать сборки, которые имеют одинаковые идентификаторы, но разные пути; он будет загружать только первую такую ​​сборку, что снова приводит меня к одному и тому же вопросу, какова идентичность сборок?

+6

Серьезно я также иногда думаю, что MS должна нанимать лучших писателей или что-то еще, поскольку предложения не всегда понятны ... – Tarik

+7

См. Также [* недокументация *] (http://www.codinghorror.com/blog/2005/ 11/avoiding-undocumentation.html) –

+0

@ColonelPanic MS может сказать, что все документировано ... но с помощью фактора zeroooo. – Legends

ответ

80

Это ясно?

// 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); 

Редактировать: ответить на поставленные Вами вопросы в вашем пересмотренным вопрос, вы определенно хотите читать Suzanne Cook on Assembly Identity.

Существует множество правил, которые регулируют загрузку сборок, а некоторые из них связаны с тем, как они разрешают зависимости - если ваша AssemblyA зависит от AssemblyB, где .NET должен искать AssemblyB? В глобальном кэше сборок в том же каталоге он нашел AssemblyA или где-то еще полностью? Кроме того, если он находит несколько копий этой сборки, как выбрать, какой из них использовать?

LoadFrom имеет один свод правил, в то время как LoadFile имеет другой набор правил. Трудно представить себе много причин использовать LoadFile, но если вам нужно использовать отражение на разных копиях одной и той же сборки, оно есть для вас.

+1

Является ли CodeBase такой же, как Identity? – Xaisoft

+0

Нет, я просто использовал CodeBase здесь как произвольное свойство сборки, чтобы проиллюстрировать, что второй экземпляр сборки указывал на «неправильный» файл (в первом примере). Я обновляю свой ответ более подробно. –

+0

Он немного очищает его, но как путь1 и путь2 указывают на разные копии одной и той же сборки на диске при использовании LoadFrom, а при использовании LoadFile путь1 и путь2 указывают на разные сборки. Каков пример того, какие пути1 и путь2 будут? Спасибо за ваше терпение. – Xaisoft

50

От Suzanne Cook's blog:

LoadFile против LoadFrom

Будьте осторожны - это не то же самое вещь.

LoadFrom() проходит через Fusion и может быть перенаправлен на другую узла на другой путь, но с том же идентичность, если один уже загружен в контексте LoadFrom.

LoadFile() не связывается через Fusion вообще - загрузчик просто идет вперед и загружает точно * то, что запрашивал абонент . Он не использует контекст Load или LoadFrom .

Итак, LoadFrom() обычно дает вам то, что вы запросили , но не обязательно. LoadFile() для тех, кто действительно, действительно хочет точно, что запрашивается. (* Однако, начиная с v2, политика будет применяться как к LoadFrom() и LoadFile(), так LoadFile() не будет обязательно быть именно то, что было предложено . Кроме того, начиная с v2, если сборка с ее идентичности в GAC, копия GAC будет использоваться вместо использования ReflectionOnlyLoadFrom() загрузить именно то, что вы хотите -.. но, отметить, что сборки загружаются таким образом не может быть выполнена)

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

См. here.

См. Также статью Choosing a Binding Context в том же блоге.

+0

Спасибо, я проверил блог, я обновил сообщение с некоторыми вопросами относительно документации msdn. – Xaisoft

+0

@ Xaisoft - блог Сузанны Кук снова приходит на помощь с ответом на идентификацию ассемблеров. См. Http://blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx. Это, по сути, «отображаемое имя сборки», и это что-то вроде: «System, Version = 1.0.3300.0, Culture = neutral, PublicKeyToken = b77a5c561934e089», поэтому включает как фактическое имя сборки, так и номер версии вместе с другой идентифицирующей информацией (например, PublicKeyToken и т. Д.). – CraigTP

+0

Любопытный, это Suzanne Cook the Reflection Guru :) – Xaisoft

5

одна разница, что я заметил:

Assembly.LoadFile - Грузы сборки в различных AppDomain с ограниченными правами пользователя (разностное principel). операции, такие как сериализация/десерилизация, не могут быть выполнены.

Assembly.LoadFrom - Загружает сборку в том же AppDomain с теми же правами пользователя (тот же принцип).

2

Примечание. Если одна сборка загружена с использованием пути 8.3, а затем с пути не-8.3, они будут рассматриваться как разные сборки, хотя они представляют собой одну и ту же физическую DLL.

32

После многих царапин на голове я обнаружил разницу сегодня днем.

Я хотел загрузить DLL во время выполнения, а DLL - в другой каталог. У DLL были свои собственные зависимости (DLL), которые также жили в том же каталоге.

LoadFile(): Загрузите определенную DLL, но не зависимости. Поэтому, когда первый вызов был сделан из DLL в одну из этих других DLL, он выдал исключение FileNotFoundException.

LoadFrom(): Загрузите указанную мной DLL, а также все зависимости, которые проживали в этом каталоге.

+3

Это была моя проблема! Я получаю «FileNotFoundException» при создании нового экземпляра объекта, определенного в сборке, на который ссылается сборка, которую я только что загрузил '.LoadFile'. Изменение этого параметра на '.LoadFrom' появилось, чтобы исправить эту проблему, но я не знал, почему! Спасибо – Connell

+1

Спасибо, у меня была такая же проблема. –

0

В моем случае мне просто нужно просто удалить кэш ASP-приложения, расположенный по адресу C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files. Он восстанавливается при первом запуске сайта. Обязательно сначала остановите IIS.

Надеюсь, это поможет кому-то, как это было для меня.

-1

Согласно документации:

LoadFile (String): Загружает содержимое файла сборки данного файла путь.

LoadFrom (String): загружает сборку с указанием ее имени или пути к файлу.