2010-06-03 24 views
13

Benim varsayımım, her zaman CLR'nin uygulama etki alanının başlangıcında ihtiyaç duyduğu tüm DLL'leri yüklediği varsayımıydı. Ancak, bu varsayımı sorgulatan bir örnek yazdım. Uygulamamı başlatıyorum ve kaç modül yüklendiğini kontrol ediyorum. DLL'ler CLR tarafından nasıl yüklenir?

Process[] ObjModulesList; 
ProcessModuleCollection ObjModulesOrig; 

//Get all modules inside the process 
ObjModulesList = Process.GetProcessesByName("MyProcessName"); 
// Populate the module collection. 
ObjModulesOrig = ObjModulesList[0].Modules; 

Console.WriteLine(ObjModulesOrig.Count.ToString()); 

Sonra kodun aynısını repeate ve benim sayım farklıdır. Ek DLL C: \ WINNT \ system32 \ version.dll dosyasıdır.

Sayımların neden farklı olacağına dair kafam çok karışık.

Birisi, CLR'nin ne yaptığını ve bu şeyin nasıl yüklendiğini ve bunun mantığıyla ilgilenebilir mi?

cevap

21

Don Box'ın mükemmel Essential Net kopyalanan aşağıdaki. (Mevcut here)
(ve, imho, bir türlü profesyonel Net geliştirici için olması gerekir)

CLR Yükleyici

CLR Yükleyici, yükleme ve başlatma meclisleri, modüllerin kaynakları sorumludur ve türleri. CLR yükleyici, yükleyebileceği kadar az yükler ve başlatır. Win32 yükleyicisinden farklı olarak, CLR yükleyicisi, alt modülleri (veya montajları) otomatik olarak çözmez ve yüklemez. Aksine, alt parçalar yalnızca gerçekten gerekliyse istek üzerine yüklenir (Visual C++ 6.0'ın gecikme yükleme özelliğiyle olduğu gibi). Bu sadece program başlatma süresini hızlandırmaz, aynı zamanda çalışan bir program tarafından tüketilen kaynak miktarını da azaltır. CLR'de, yükleme tipik olarak türlere göre tam zamanında (JIT) derleyici tarafından tetiklenir. JIT derleyici bir yöntem gövdesini CIL'den makine koduna dönüştürmeye çalıştığında, türün alanlarının tür tanımlarının yanı sıra bildiren türün tür tanımına erişmesi gerekir. Dahası, JIT derleyicisinin, JIT ile derlenen yöntemin herhangi bir yerel değişkeninin veya parametresinin kullandığı tip tanımlarına erişmesi gerekir. Bir yükleme, hem montaj hem de tip tanımını içeren modülü yüklemeyi gerektirir. Bu yükleme tipleri (ve montajlar ve modüller) politikası talep üzerine kullanılmayan bir programın parçalarının hiçbir zaman belleğe alınmadığı anlamına gelir. Ayrıca, çalışan bir uygulamanın, uygulama sırasında bu dosyalarda bulunan türlere ihtiyaç duyulduğu için zamanla yüklenen yeni montajları ve modülleri sıklıkla göreceği anlamına gelir. Bu istediğiniz davranış değilse, iki seçeneğiniz vardır.Birisi, yükleyiciyle açıkça etkileşim kurmak istediğiniz türlerin gizli statik alanlarını açıkça belirtmektir.

Yükleyici genellikle işini sizin adınıza dolaylı olarak yapar. Geliştiriciler, yükleyici ile montaj yükleyicisi aracılığıyla açıkça etkileşim kurabilir. Montaj yükleyicisi, System.Reflection.Assembly sınıfındaki LoadFrom statik yöntemiyle geliştiricilere maruz kalmaktadır. Bu yöntem, bir dosya sistemi yolu veya montaj bildirimini içeren modülü tanımlayan tekdüzen bir kaynak konum belirleyicisi (URL) olabilen bir KODBOLU dizesini kabul eder. Belirtilen dosya bulunamazsa, yükleyici System.FileNotFoundException istisnasını atar. Belirtilen dosya bulunabilir, ancak bir montaj bildirimi içeren bir CLR modülü değilse, yükleyici bir System.BadImageFormatException istisnasını atar. Son olarak, CODEBASE, file: dışında bir şema kullanan bir URL ise, arayan WebPermission erişim haklarına sahip olmalıdır veya System.SecurityException istisnası atılır. Ayrıca, file: dışındaki protokollere sahip URL'lerde yapılan yüklemeler, yüklenmeden önce ilk önce indirme önbelleğine indirilir.

Liste 2.2, file://C:/usr/bin/xyzzy.dll'da bulunan bir derlemeyi yükleyen ve daha sonra AcmeCorp.LOB.Customer adında bulunan türün bir örneğini oluşturan basit bir C# programını gösterir. Bu örnekte, arayan tarafından sağlanan tüm montajın fiziksel yeridir. Bir program montaj yükleyiciyi bu şekilde kullandığında, CLR, sürüm numarası da dahil olmak üzere düzeneğin dört bölümlü adını yoksayar. Konuma göre yükleme takımları bir miktar ilginç olsa da, en çok birleştirme işleri çözümleyici kullanılarak adıyla yüklenir

using System; 
using System.Reflection; 
public class Utilities { 
    public static Object LoadCustomerType() { 
    Assembly a = Assembly.LoadFrom(
        "file: //C:/usr/bin/xyzzy. dll") ; 
    return a.CreateInstance("AcmeCorp.LOB.Customer") ; 
    } 
} 

Açık bir CODEBASE bir yapısı yükleme

Örnek 2. 2.. Derleme çözümleyicisi, derleme yükleyiciyi kullanarak hangi temel dosyanın belleğe yükleneceğini belirlemek için dört bölümlü derleme adını kullanır. Figure 2.9'da gösterildiği gibi, bu ad-çözme çözümleme işlemi, uygulamanın barındırıldığı dizin, sürüm oluşturma ilkeleri ve diğer yapılandırma ayrıntılarını (tümü bu bölümde daha sonra ele alınmaktadır) içeren çeşitli faktörleri hesaba katar.

Montaj çözücü, System.Reflection.Assembly sınıfının Load yöntemi aracılığıyla geliştiricilere açıktır. Listeleme 2.3'de gösterildiği gibi, bu yöntem dört bölümlü bir montaj adını kabul eder (ya bir dize olarak ya da AssemblyName referansı olarak) ve yüzeysel olarak montaj yükleyicinin maruz kaldığı LoadFrom yöntemine benzer gibi görünür. Benzerlik sadece cilt derinliğidir, çünkü Load metodu ilk önce derleme çözümleyicisini oldukça karmaşık bir dizi işlem kullanarak uygun bir dosya bulmak için kullanır. Bu işlemlerden ilki, istenen montajın hangi versiyonunun yükleneceğini belirlemek için bir versiyon politikası uygulamaktır.

Örnek 2.3. Montaj Çözücü

using System; 
using System.Reflection; 
public class Utilities { 
    public static Object LoadCustomerType() { 
    Assembly a = Assembly.Load(
     "xyzzy, Version=1. 2. 3.4, " + 
     "Culture=neutral, PublicKeyToken=9a33f27632997fcc") ; 
    return a.CreateInstance("AcmeCorp.LOB.Customer") ; 
    } 
} 
+0

Bir modülün önceden hatlar yüklenmesi mümkün mü?Yoksa nesnenin yaratıldığı ikinci yüklü mi? (dll, projenin referanslar bölümüne eklenir.) – priehl

+0

@priehl, yr soru, tasarım zamanında bahsettiğiniz gibi geliyor ("... dll, projenin referans kısmına eklenir"). Bu, herhangi bir şeyin yüklenmesine neden olmaz. Yükleme, yalnızca program çalışırken ve daha sonra montaj veya modül düzeyinde gerçekleşmez, aslında, Type düzeyinde olur, yani CLR, çalışan programın ilk kez çalıştırdığı bir tür için kodu yükler. henüz yüklenmemiş bir türden bir IL kodu satırı yürütmek. –

+0

Tamam. Bunu test etmek için aşağıdaki // Örneğimde yöntemi kullanarak yüklenen modülleri kontrol ettim. // Yeni bir Excel.Application oluşturun (tasarım zamanında dll eklenmiştir) // Yüklenmiş modülleri denetleyin. Yüklenmiş modüllerin 1. denetiminin Microsoft.Office.Interop.Excel.dll dosyasını içermemesi beklenir, ancak bunu yapar. Bu durum, dll tarafından tanımlanan Türü kullanılıncaya kadar yükleme gerçekleşmeyeceği için nasıl olabilir? – priehl

1

CLR, aksamları isteğe bağlı olarak yükler. Bir yöntemi yürüttüğünüzde, nerede olduğunu (hangi modül vb.) Görmeye bakar ve yüklenmezse yükler. İşte

yükleme derlemeler hakkında CLR performans ve görüşmelere bir article geçerli:

CLR just-in-time (JIT) bu yöntemi içinde başvurulan tüm derlemeler yüklenmesi gereken Başlat yöntemini derler

. Bu, istisna işleyicisinde başvurulan tüm derlemelerin, uygulamanın çalıştırıldığı çoğu zaman gerekli olmasalar da yükleneceği anlamına gelir.

Bu article, SilverLight içindir, ancak CLR'de ne olduğu hakkında biraz konuşur.

0

COM DLL'leri, karşılık gelen COM nesnesi oluşturulduğunda istek üzerine yüklenir. Bu aynı zamanda non-COM dlls ile de olabilir.

+0

Bunun doğru olduğunu düşünmüyorum. Bunu özellikle test ediyorum. Yukarıda yaptığım gibi yüklenen modülleri kontrol ediyorum. Sonra bir Microsoft.Office.Interop.Excel oluşturur. Uygulama nesnesi ve sonra yüklenen modülleri denetlerim ve her iki durumda da Excel.dll modülü listelenir. – priehl

+0

excel nesnesini ne zaman başlatıyorsunuz? Kevin tarafından yukarıda belirtildiği gibi başlangıç ​​yönteminde atıfta bulunulan tüm derlemeler başlangıçta yüklenecektir. Sunucunuzu başka bir yönteme taşımayı deneyin ve ne olduğunu görün. – Vlad

1

kullanarak bir Assembly yükleme Bu kapalı soru biraz, ama talep üzerine gerçekleşmesi sahip tercih etmezse, tek seferde tüm meclisleri yükleyebilirsiniz. Bunun gibi bir şey

foreach (AssemblyName asn in Assembly.GetExecutingAssembly().GetReferencedAssemblies()) 
{ 
    var asm = Assembly.Load(fn); 
    // I've found get types does a good job of ensuring the types are loaded. 
    asm.GetTypes(); 
}