Skip to content

AppDomain.AssemblyResolve

Şöyle bir durum söz konusu olduğunu varsayalım; yazdığınız bir uygulama var ve uygulama ile birlikte değişmeyecek yapıda oldukça fazla boyutlu referans kütüphaneler vermeniz gerekli. Bir tür SDK olabilir ya da arabirim kütüphaneleri olabilir vs. Uygulama ile verelim olsun gitsin bir yaklaşımdır evet, ama 100 kb lik bir uygulama yazdınız ve onun refere ettiği bu assembly’ler 10 mb ise ne yapacaksınız. Her yeni sürümde kullanıcıya 100 kb aldırıp işi kurtarmak varken kullanıcılara bir deployment eziyeti mi yapacaksınız? Bu durumlarda ilk kullanılması gereken GAC (Global Assembly Cache) dir haliyle. O kütüphaneyi proje içinde kullanmak istediğiniz anda uygulama yolu ve standart yükleme yollarında assembly bulunamaz ise GAC’a bakılır. Ve kütüphane GAC içerisinden çalıştırılır. Farkında olun ya da olmayın System namespace’i altındaki bütün kütüphaneler GAC içerisinden bu anlatılan şekilde çağrılmaktadır. Yoksa hiç biriniz mesela mscorlib.dll’i projeleriniz ile birlikte vermiyorsunuz değil mi?

Neyse sorun halloldu gibi gözükebilir fakat GAC için şöyle bir zorunluluk var, GAC içerisine kurulacak bir assembly mutlaka ve mutlaka “strong name” sahibi olması lazım, bir başka anlamda dijital imza içermesi gerekli. Bunun türlü türlü sebebleri var, sorun o değil, sorun strong name sahibi olmayan bir assembly var ise ne yapacağımız. Birinci akla gelen assembly’nin imzalanması durumu, bir şekilde yapılabilir mümkündür. Ama diyelim ki bu assembly de başka assembly’leri refere ediyor, o da başkalarını… böyle bir durumda olayı işkenceye çevirmemek için bir başka sistem mevcut.

AppDomain içerisinde bir event tanımlanmış. Adı AssemblyResolve ve parametre olarak ResolveEventArgs getiriyor. İçerisinden yüklenmek istenilen assembly’ye ait yükleme verisine ulaşılabiliyor. Bu yükleme verisinde assembly’nin adı versiyonu gibi bilgiler mevcut. AppDomain ilk oluşturulduğu yerde bu event’i bir fonksiyona bağlarsanız, istediğiniz klasörden, ortamdan ya da internetten bu gerek duyulan assembly’yi bulabilir ve sonuç olarak döndürebilirsiniz.

        Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
            AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf AssemblyResolve
        End Sub

        Dim localAssemblyCache As String = "C:\DenemeSDK"
        Public Function AssemblyResolve(ByVal sender As Object, ByVal args As System.ResolveEventArgs) As System.Reflection.Assembly
            Dim sp() As String = args.Name.Split(",")

            Dim assemblyPath As String = Path.Combine(localAssemblyCache, sp(0) & ".dll")
            If File.Exists(assemblyPath) Then
                Return Assembly.LoadFrom(assemblyPath)
            Else
                Return Nothing
            End If
        End Function

Şimdi örneği incelersek, uygulama başladığı anda event’i bir fonksiyona bağlıyoruz. Sonra istek geldiğinde yükleme cümlesinden assembly’ye ait adı alıp klasörümüz içerisinde arıyoruz, eğer bulur isek mevcut domain’e assembly’nin yüklenmesi için LoadFrom fonksiyonunu çağırıp dönen instance’ı fonksiyondan döndürüyoruz. Eğer yok ise bir sonuç döndürmüyoruz. Bu noktada bu doğrulamalardan mesela versiyon bilgisini ve ya strong name durumunu da kontrol edebilirdik. Ve ya ilgili assembly’yi klasörde bulamayınca bir web servisinden isteyebilir, bulunur ise indirip yükler ve öyle de bir sonuç döndürebilirdik vs. vs. Uzun sözün kısası, tüm deployment sistemimizi baştan aşağı bu event sayesinde kendimiz kurabiliriz.

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*