LoadFile ve LoadFrom with .NET Assemblies arasındaki fark nedir?


126

Msdn belgelerine bakıyordum LoadFileve LoadFrombir montajı kullanmak ve yüklemek arasındaki farkın tam olarak ne olduğu konusunda hala biraz kafam karışık . Birisi onu daha iyi tanımlamak için bir örnek veya bir benzetme sağlayabilir mi? MSDN belgeleri kafamı daha fazla karıştırdı. Ayrıca, montajı yalnızca yansıma modunda yüklemesi dışında ReflectionOnlyLoadFromaynıdır LoadFrom.

.NET deneyimim en iyisi olmadığından, LoadFile kullanan MSDN belgeleriyle ilgili bazı soruları burada bulabilirsiniz:

1) LoadFileAynı Kimliğe sahip ancak farklı yollarda bulunan meclisleri incelemek ne anlama geliyor ? Kimlik (örnek) nedir?

2) LoadFileDosyaları 'LoadFrom Bağlamına' yüklemediğini ve yükleme yolunu kullanarak bağımlılıkları çözmediğini belirtir . Bu ne anlama geliyor, birisi örnek verebilir mi?

3) Son olarak, LoadFilebu sınırlı senaryoda yararlı olduğunu belirtir çünkü LoadFrom aynı kimliklere, ancak farklı yollara sahip derlemeleri yükleyemez; sadece bu tür ilk montajı yükleyecektir, bu da beni yine aynı soruya getiriyor, meclislerin kimliği nedir?


10
Cidden, cümleler her zaman anlaşılabilir olmadığı için bazen MS'in daha iyi yazarları veya başka bir şeyi işe alması gerektiğini düşünüyorum ...
Tarik


1
@ColonelPanic MS, her şeyin belgelendiğini söyleyebilir ... ancak sıfır ooo yardım faktörü ile.
Efsaneler

Yanıtlar:


96

Bu onu temizliyor mu?

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

Düzenleme : Gözden geçirilmiş sorunuzda sorduğunuz soruları cevaplamak için , Montaj Kimliği üzerine Suzanne Cook'u kesinlikle okumak istersiniz .

Derlemelerin nasıl yükleneceğini yöneten birçok kural vardır ve bunlardan bazıları bağımlılıkları nasıl çözdükleriyle ilgilidir - AssemblyA'nız AssemblyB'ye bağımlıysa, .NET, AssemblyB'yi bulmak için nereye bakmalıdır? Global Assembly Cache'de, AssemblyA'yı bulduğu dizinde mi yoksa tamamen başka bir yerde mi? Ayrıca, bu derlemenin birden fazla kopyasını bulursa, hangisini kullanacağını nasıl seçmelidir?

LoadFrombir kurallar dizisi varken LoadFilebaşka bir kurallar dizisi vardır. Kullanmak için pek çok neden hayal etmek zor LoadFile, ancak aynı montajın farklı kopyalarında yansımayı kullanmanız gerekiyorsa, bu sizin için var.


2
CodeBase, Kimlik ile aynı mı?
Xaisoft

Hayır, burada CodeBase'i, ikinci Assembly örneğinin (ilk örnekte) 'yanlış' dosyaya işaret ettiğini göstermek için derlemenin keyfi bir özelliği olarak kullandım. Cevabımı daha fazla ayrıntıyla güncelliyorum.
Jeff Sternal

1
Biraz temizler, ancak yol1 ve yol2, LoadFrom kullanılırken ve LoadFile kullanılırken, yol1 ve yol2 farklı derlemeleri gösterirken diskteki aynı derlemenin farklı kopyalarına nasıl işaret eder. Yol1 ve yol2'nin ne olacağına dair bir örnek nedir? Sabrınız için teşekkürler.
Xaisoft

Değer eşitliği için neden iki dizi referansını kontrol ediyorsunuz string.Compare(x, y) == 0? Sanırım x == yorayı ister misin ? Muğlak nedenlerden ötürü kültüre bağlı eşitlik kontrolü istiyorsanız string.Equals(x, y, StringComparison.CurrentCulture), örneğin yazmak daha açıktır .
Jeppe Stig Nielsen

@JeffSternal "Montaj Kimliğinde Suzanne Cook" bağlantısı burada kırılmış görünüyor ...
Martin Verjans

61

Gönderen Suzanne Cook'un blogunda :

LoadFile vs LoadFrom

Dikkatli olun - bunlar aynı şey değil.

LoadFrom (), Fusion'dan geçer ve farklı bir yolda, ancak LoadFrom bağlamında zaten yüklenmişse aynı kimliğe sahip başka bir montaja yeniden yönlendirilebilir.

LoadFile (), Fusion aracılığıyla hiçbir şekilde bağlanmaz - yükleyici yalnızca devam eder ve arayanın * istediği şeyi tam olarak yükler. Load veya LoadFrom bağlamını kullanmaz.

Dolayısıyla, LoadFrom () size genellikle istediğinizi verir, ancak zorunlu değildir. LoadFile (), gerçekten, gerçekten tam olarak istenen şeyi isteyenler içindir. (* Bununla birlikte, v2'den başlayarak, politika hem LoadFrom () hem de LoadFile () 'ye uygulanacaktır, bu nedenle LoadFile () tam olarak istenen şey olmayacaktır. Ayrıca, v2'den başlayarak, kimliğine sahip bir derleme GAC yerine GAC kopyası kullanılacaktır. Tam olarak istediğiniz şeyi yüklemek için ReflectionOnlyLoadFrom () kullanın - ancak bu şekilde yüklenen derlemelerin yürütülemeyeceğini unutmayın.)

LoadFile () bir yakalamaya sahip. Bağlama bağlamı kullanmadığından, bağımlılıkları kendi dizininde otomatik olarak bulunmaz. Yük bağlamında mevcut değillerse, bunlara bağlanmak için AssemblyResolve olayına abone olmanız gerekir.

Buraya bakın .

Aynı blogdaki Bağlayıcı Bağlam Seçme makalesine de bakın .


Teşekkürler, bloga göz atacağım, mesajımı msdn dokümantasyonu ile ilgili bazı sorularla güncelledim.
Xaisoft

@Xaisoft - Suzanne Cook'un blogu, Assemblies Identity'nin cevabı ile tekrar kurtarmaya geliyor. Blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx sayfasına bakın . Esasen bir "derleme görünen adı" dır ve şuna benzer: "Sistem, Sürüm = 1.0.3300.0, Kültür = nötr, PublicKeyToken = b77a5c561934e089" dolayısıyla hem derlemenin gerçek adını hem de sürüm numarasını diğer tanımlayıcı bilgilerle birlikte içerir ( PublicKeyToken vb.).
CraigTP

1
Fusion hakkında konuşurken neyi kastediyor?
Xaisoft

1
Gerçekten de Jeff yerinde. Fusion alt sistemi hakkında güzel bir öğretici ve .NET'te derlemeleri yükleme teknolojisi için şu bağlantıya bakın: grimes.demon.co.uk/workshops/fusionWS.htm
CraigTP

1
Hızlı bir güncelleme, yukarıdaki URL'nin (grimes.demon.co.uk/workshops/fusionWS.htm) artık geçerli olmadığını ve şimdi şu
adrese

45

Çok fazla kafa karıştırdıktan sonra bu öğleden sonra kendimde bir fark keşfettim.

Çalışma zamanında bir DLL yüklemek istedim ve DLL başka bir dizinde yaşıyordu. Bu DLL'nin aynı dizinde bulunan kendi bağımlılıkları (DLL'ler) vardı.

LoadFile (): Belirli DLL'yi yükledi, ancak bağımlılıkları yüklemedi. Dolayısıyla, DLL içinden bu diğer DLL'lerden birine ilk çağrı yapıldığında, bir FileNotFoundException attı.

LoadFrom (): Belirttiğim DLL'yi ve o dizinde yaşayan tüm bağımlılıkları yükledim.


4
Bu benim sorunumdu! FileNotFoundExceptionYeni yüklediğim montaj tarafından referans verilen bir montajda tanımlanan bir nesnenin yeni bir örneğini oluştururken alıyordum .LoadFile. .LoadFromSorunu gidermek için bunu değiştirmek göründü, ancak nedenini bilmiyordum! Teşekkürler
Connell

1
Teşekkür ederim, ben de aynı sorunu yaşıyordum.
Ivandro IG Jao

4

Not: Bir derleme bir 8.3 yolu kullanılarak yüklenirse ve ardından 8.3 olmayan bir yoldan yüklenirse, aynı fiziksel DLL olsalar bile farklı derlemeler olarak görülecektir.



0

fark ettiğim bir fark şudur:

Assembly.LoadFile - Sınırlı kullanıcı haklarıyla (farklılık ilkesi) farklı AppDomain'deki derlemeyi yükler. serilizasyon / deserilizasyon gibi işlemler yapılamadı.

Assembly.LoadFrom - Aynı AppDomain'deki aynı kullanıcı haklarıyla (aynı ilke) derlemeyi yükler.


3
Bu doğru değil. Assembly.LoadFile'ın bir montajı başka bir AppDomain'e yüklediğine sizi inandıran nedir?
Sven Mawby

0

Benim durumumda, @ konumunda bulunan ASP uygulama önbelleğini silmem gerekti C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files. Site ilk çalıştırıldığında yeniden inşa edilir. Önce IIS'yi durdurduğunuzdan emin olun.

Umarım bu, benim için yaptığı gibi birine yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.