ความแตกต่างระหว่าง LoadFile และ LoadFrom กับ. NET Assemblies?


126

ฉันกำลังดูเอกสาร msdn และฉันก็ยังสับสนเล็กน้อยว่าอะไรคือความแตกต่างระหว่างการใช้LoadFileและLoadFromเมื่อโหลดแอสเซมบลี ใครสามารถยกตัวอย่างหรือการเปรียบเทียบเพื่ออธิบายให้ดีขึ้นได้ เอกสาร MSDN ทำให้ฉันสับสนมากขึ้น นอกจากนี้ยังReflectionOnlyLoadFromเหมือนกับLoadFromยกเว้นว่าจะโหลดแอสเซมบลีในโหมดสะท้อนแสงเท่านั้น

เนื่องจากประสบการณ์. NET ของฉันไม่ได้ดีที่สุดนี่คือคำถามบางส่วนเกี่ยวกับเอกสาร MSDN โดยใช้ LoadFile:

1) การLoadFileตรวจสอบแอสเซมบลีที่มีเอกลักษณ์เหมือนกัน แต่อยู่คนละเส้นทางหมายความว่าอย่างไร ตัวตน (ตัวอย่าง) คืออะไร?

2) ระบุว่าLoadFileไม่โหลดไฟล์ลงใน 'LoadFrom Context' และไม่แก้ไขการอ้างอิงโดยใช้โหลดพา ธ หมายความว่าอย่างไรใครสามารถให้ตัวอย่างได้

3) สุดท้ายนี้ระบุว่าLoadFileมีประโยชน์ในสถานการณ์ที่ จำกัด นี้เนื่องจาก LoadFrom ไม่สามารถโหลดแอสเซมบลีที่มีอัตลักษณ์เดียวกัน แต่มีพา ธ ต่างกัน มันจะโหลดแอสเซมบลีแรกเท่านั้นซึ่งทำให้ฉันเจอคำถามเดิมอีกครั้งอัตลักษณ์ของแอสเซมบลีคืออะไร?


10
อย่างจริงจังฉันยังคิดว่าบางครั้ง MS ควรจ้างนักเขียนที่ดีกว่าหรืออย่างอื่นเนื่องจากประโยคต่างๆไม่สามารถเข้าใจได้เสมอไป ...
Tarik


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 ควรมองหา AssemblyB ที่ไหน ใน Global Assembly Cache ไดเรกทอรีเดียวกันกับที่พบ AssemblyA หรือที่อื่นทั้งหมด? นอกจากนี้หากพบสำเนาหลายชุดของชุดประกอบนั้นควรเลือกใช้อย่างไร?

LoadFromมีกฎชุดเดียวในขณะที่LoadFileมีกฎอีกชุดหนึ่ง มันยากที่จะจินตนาการถึงเหตุผลมากมายที่จะใช้LoadFileแต่ถ้าคุณจำเป็นต้องใช้การไตร่ตรองในสำเนาต่าง ๆ ของแอสเซมบลีเดียวกันก็มีให้สำหรับคุณ


2
CodeBase เหมือนกับ Identity หรือไม่
Xaisoft

ไม่ฉันเพิ่งใช้ CodeBase ที่นี่เป็นคุณสมบัติตามอำเภอใจของแอสเซมบลีเพื่อแสดงให้เห็นว่าอินสแตนซ์ Assembly ที่สองชี้ไปที่ไฟล์ 'ผิด' (ในตัวอย่างแรก) ฉันกำลังอัปเดตคำตอบพร้อมรายละเอียดเพิ่มเติม
Jeff Sternal

1
มันล้างข้อมูลเล็กน้อย แต่ path1 และ path2 ชี้ไปยังสำเนาที่แตกต่างกันของแอสเซมบลีเดียวกันบนดิสก์อย่างไรเมื่อใช้ LoadFrom และเมื่อใช้ LoadFile path1 และ path2 ชี้ไปยังแอสเซมบลีที่แตกต่างกัน อะไรคือตัวอย่างของ path1 และ path2 ที่จะเป็นอย่างไร? ขอบคุณสำหรับความอดทนของคุณ.
Xaisoft

เหตุใดคุณจึงตรวจสอบการอ้างอิงสองสตริงเพื่อความเท่าเทียมกันของค่าด้วยstring.Compare(x, y) == 0? ฉันคิดว่าคุณต้องการที่x == yนั่น? หากเหตุผลที่คลุมเครือคุณไม่ต้องการให้มีการตรวจสอบความเท่าเทียมกันตามวัฒนธรรมก็ควรเขียนให้ชัดเจนstring.Equals(x, y, StringComparison.CurrentCulture)กว่านี้
Jeppe Stig Nielsen

@JeffSternal ลิงก์ "Suzanne Cook on Assembly Identity" ดูเหมือนจะเสียที่นี่ ...
Martin Verjans

61

จากบล็อกของ Suzanne Cook :

LoadFile กับ LoadFrom

ระวัง - นี่ไม่ใช่สิ่งเดียวกัน

LoadFrom () ผ่าน Fusion และสามารถเปลี่ยนทิศทางไปยังแอสเซมบลีอื่นที่พา ธ อื่นได้ แต่ด้วยเอกลักษณ์เดียวกันนั้นหากมีการโหลดในบริบท LoadFrom แล้ว

LoadFile () ไม่ผูกผ่าน Fusion เลย - ตัวโหลดจะดำเนินการต่อและโหลดสิ่งที่ผู้โทรร้องขอ ไม่ได้ใช้บริบท Load หรือ LoadFrom

ดังนั้น LoadFrom () มักจะให้สิ่งที่คุณขอ แต่ไม่จำเป็น LoadFile () สำหรับผู้ที่ต้องการสิ่งที่ต้องการจริงๆ (* อย่างไรก็ตามตั้งแต่ v2 เป็นต้นไปนโยบายจะถูกนำไปใช้กับทั้ง LoadFrom () และ LoadFile () ดังนั้น LoadFile () จึงไม่จำเป็นต้องตรงตามที่ร้องขอนอกจากนี้เริ่มต้นใน v2 หากแอสเซมบลีที่มีข้อมูลประจำตัวอยู่ใน GAC จะใช้สำเนา GAC แทนใช้ ReflectionOnlyLoadFrom () เพื่อโหลดสิ่งที่คุณต้องการ - แต่โปรดทราบว่าแอสเซมบลีที่โหลดด้วยวิธีนั้นไม่สามารถดำเนินการได้)

LoadFile () มีการจับ เนื่องจากไม่ได้ใช้บริบทที่มีผลผูกพันจึงไม่พบการอ้างอิงโดยอัตโนมัติในไดเรกทอรี หากไม่มีในบริบทการโหลดคุณจะต้องสมัครสมาชิกเหตุการณ์ AssemblyResolve เพื่อเชื่อมโยงกับเหตุการณ์เหล่านี้

ดูที่นี่ .

นอกจากนี้โปรดดูบทความการเลือกบริบทการผูกในบล็อกเดียวกัน


ขอบคุณฉันจะตรวจสอบบล็อกฉันอัปเดตโพสต์ของฉันพร้อมกับคำถามบางอย่างเกี่ยวกับเอกสาร msdn
Xaisoft

@Xaisoft - บล็อกของ Suzanne Cook กลับมาช่วยเหลืออีกครั้งพร้อมคำตอบของ Assemblies Identity ดูblogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx โดยพื้นฐานแล้วมันคือ "ชื่อที่แสดงของแอสเซมบลี" และนี่คือสิ่งที่ชอบ: "System, Version = 1.0.3300.0, Culture = neutral, 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
ขอบคุณฉันประสบปัญหาเดียวกัน
Ivandro IG Jao

4

หมายเหตุ: หากแอสเซมบลีหนึ่งถูกโหลดโดยใช้พา ธ 8.3 จากนั้นจากพา ธ ที่ไม่ใช่ 8.3 จะถูกมองว่าเป็นแอสเซมบลีที่แตกต่างกันแม้ว่าจะเป็น DLL ทางกายภาพเดียวกันก็ตาม



0

ความแตกต่างอย่างหนึ่งที่ฉันสังเกตเห็นคือ:

Assembly.LoadFile - โหลดแอสเซมบลีใน AppDomain ที่แตกต่างกันโดยมีสิทธิ์ผู้ใช้ที่ จำกัด (หลักการที่แตกต่างกัน) ไม่สามารถดำเนินการเช่น serilization / deserilization

Assembly.LoadFrom - โหลดแอสเซมบลีใน AppDomain เดียวกันที่มีสิทธิ์ผู้ใช้เดียวกัน (หลักการเดียวกัน)


3
สิ่งนี้ไม่ถูกต้อง อะไรทำให้คุณเชื่อว่า Assembly.LoadFile โหลดแอสเซมบลีลงใน AppDomain อื่น
Sven Mawby

0

ในกรณีของฉันฉันเพิ่งมีเพียงแค่ลบแคชใช้ ASP อยู่ C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files@ สร้างขึ้นใหม่เมื่อมีการเรียกใช้ไซต์ครั้งแรก อย่าลืมหยุด IIS ก่อน

หวังว่านี่จะช่วยใครบางคนเหมือนที่เคยทำกับฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.