Відмінність LoadFile від LoadFrom від .NET зборів?


126

Я переглядав документацію msdn, і я все ще трохи розгублений у тому, яка саме різниця між використанням LoadFileта LoadFromзавантаженням збірки. Чи може хтось навести приклад чи аналогію, щоб краще описати його. Документація MSDN мене більше збентежила. Також, це ReflectionOnlyLoadFromте саме, що, LoadFromза винятком того, що він завантажує збірку лише у режимі відображення.

Оскільки мій досвід .NET не найбільший, ось декілька питань щодо документації MSDN за допомогою LoadFile:

1) Що означає LoadFileпідслідження збірок, які мають однакову ідентичність, але розташовані різними шляхами? Що таке особистість (приклад)?

2) У ньому зазначено, що LoadFileне завантажує файли у "LoadFrom Context" і не розв'язує залежності, використовуючи шлях завантаження. Що це означає, чи може хтось навести приклад?

3) Нарешті, він заявляє, що LoadFileце корисно в цьому обмеженому сценарії, оскільки LoadFrom не може завантажувати збірки, що мають однакові ідентичності, але різні шляху; вона завантажить лише першу таку збірку, що знову підводить мене до того ж питання, що таке ідентичність збірок?


10
Серйозно я також думаю, що іноді МС повинен найняти кращих авторів чи щось інше, оскільки речення не завжди зрозумілі ...
Тарік


1
@ColonelPanic MS може сказати, що все задокументовано ... але за допомогою коефіцієнта допомоги zeroooo.
Легенди

Відповіді:


96

Це зрозуміло це?

// 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, але якщо вам потрібно було використовувати відображення на різних копіях однієї збірки, це для вас.


2
Чи CodeBase збігається з особою?
Xaisoft

Ні, я просто використовував CodeBase тут як довільну властивість збірки, щоб проілюструвати, що другий екземпляр асамблеї вказував на "неправильний" файл (у першому прикладі). Я оновлюю свою відповідь більш детально.
Jeff Sternal

1
Це трохи очищає його, але як шлях1 і шлях2 вказують на різні копії однієї і тієї ж збірки на диску при використанні LoadFrom та при використанні LoadFile, path1 і path2 вказують на різні збірки. Що є прикладом того, яким був би шлях1 та шлях2? Дякую за Ваше терпіння.
Xaisoft

Чому ви перевіряєте дві посилання рядків на рівність значення string.Compare(x, y) == 0? Я думаю, ти хочеш x == yтам? Якщо з незрозумілих причин ви хочете перевірити рівність, залежну від культури, це зрозуміліше написати string.Equals(x, y, StringComparison.CurrentCulture), наприклад.
Jeppe Stig Nielsen

@JeffSternal Посилання на "Сьюзен Кук про особу асемблера", здається, тут порушено ...
Мартін Вержанс

61

З блогу Сюзанні Кук :

LoadFile vs. LoadFrom

Будьте уважні - це не одне і те ж.

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

LoadFile () взагалі не зв’язується через Fusion - завантажувач просто йде вперед і завантажує саме * те, що вимагав абонент. Він не використовує ні контекст Load, ні LoadFrom.

Отже, LoadFrom () зазвичай дає вам те, про що ви просили, але не обов’язково. LoadFile () призначений для тих, хто дійсно дуже хоче саме те, що вимагається. (* Однак, починаючи з v2, політика застосовуватиметься як до LoadFrom (), так і до LoadFile (), тому LoadFile () не обов'язково буде саме тим, про що вимагали. Також, починаючи з v2, якщо збірка з її ідентичністю знаходиться в GAC, замість цього буде використана копія GAC. Використовуйте ReflectionOnlyLoadFrom (), щоб завантажити саме те, що ви хочете, - але зауважте, що завантажені таким чином збірки неможливо виконати.)

LoadFile () має улов. Оскільки він не використовує обов'язковий контекст, його залежності не знаходяться автоматично в його каталозі. Якщо вони не доступні в контексті "Завантажити", вам доведеться підписатися на подію AssemblyResolve, щоб прив'язати їх.

Дивіться тут .

Також див. Стаття про вибір обов'язкового контексту в тому самому блозі.


Дякую, я перевірю щоденник, я оновив свій пост з деякими питаннями стосовно документації msdn.
Xaisoft

@Xaisoft - Блог Сюзанні Кук знову приходить на допомогу з відповіддю на особу Асамблеї. Дивіться blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx . Це по суті "ім'я відображення збірки", і це щось на зразок: "Система, Версія = 1.0.3300.0, Культура = нейтральна, PublicKeyToken = b77a5c561934e089", тому включає в себе і фактичне ім'я збірки, і номер версії разом з іншою ідентифікаційною інформацією (наприклад PublicKeyToken тощо).
CraigTP

1
На що вона має на увазі, коли говорить про Fusion?
Xaisoft

1
Дійсно, Джефф на місці. Перейдіть за цим посиланням: grimes.demon.co.uk/workshops/fusionWS.htm для приємного підручника щодо підсистеми Fusion та технології для завантаження збірок у .NET
CraigTP

1
Лише швидке оновлення, зауважте, що вказана вище URL-адреса (grimes.demon.co.uk/workshops/fusionWS.htm) більше не є дійсною і тепер перейшла на сторінку: richardgrimes.com/workshops/fusionWS.htm
CraigTP

45

Після численних чухань в голові я сьогодні виявив різницю.

Я хотів завантажити DLL під час виконання, і DLL жив в іншому каталозі. Ця DLL мала свої власні залежності (DLL), які також жили в тому самому каталозі.

LoadFile (): завантажується конкретна DLL, але не залежність. Отже, коли перший дзвінок був зроблений з DLL в одну з інших DLL, він кинув FileNotFoundException.

LoadFrom (): Завантажив DLL, який я вказав, а також всі залежності, які існували в цьому каталозі.


4
Це була саме моя проблема! Я отримував, FileNotFoundExceptionколи створював новий екземпляр об'єкта, визначений у складі, на який посилається збірка, яку я щойно завантажив .LoadFile. Змінивши це, як .LoadFromвидалося, щоб вирішити проблему, але я не знав чому! Спасибі
Connell

1
Дякую, у мене була така ж проблема.
Івандро ІГ Яо

4

Примітка: Якщо одна збірка завантажується за допомогою шляху 8.3, а потім з не-8.3 шляху, вони будуть розглядатися як різні збірки, навіть якщо вони однакові фізичні DLL.



0

одна різниця, яку я помітив, це:

Assembly.LoadFile - завантажує збірку в різних AppDomain з обмеженими правами користувача (diffrence principel). такі операції, як серіалізація / десерилізація, не вдалося виконати.

Assembly.LoadFrom - завантажує збірку в одному AppDomain з тими ж правами користувача (той же принцип).


3
Це неправильно. Що змушує вас вважати, що Assembly.LoadFile завантажує збірку в інший AppDomain?
fr34kyn01535

0

У моєму випадку мені просто довелося просто видалити кеш додатків ASP, розташований @ C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files. Він відновлюється під час першого запуску сайту. Обов’язково спочатку зупиніть IIS.

Сподіваюсь, це допомагає комусь, як це зробило для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.