.NET in temelleri -4

.NET in temelleri -4 .NET in temelleri -4

Global Assembyler

Evet, artık private assemblyler ile ilgili tüm temel noktaları ele aldığımıza göre, onlara göre biraz daha detaylı olarak inceleyeceğimiz global  assemblylere başlayabiliriz.Bir önceki yazımızda incelediğimiz private assembly’ler  ortak olarak kullanılmasını istediğimiz kaynakları paylaşmak için oldukça pratik bir yöntem.Ancak paylaşılmasını istediğimiz kaynağı, birden fazla program için hazırlamışsak, pratikte işler biraz karışacaktır. Diyelim ki, son derece faydalı, herkesin programında kullanmak için can atacağı bir bileşenimiz var. Bunu da önceki yazılarımızda beraber oluşturduğumuz paylaşılan dll içinde saklıyoruz. Şimdi bizim bu dll’imiz son derece faydalı olduğu için birden fazla yazılımda kullanılacak, bu durumda , bu yazılımların her biri bu dll’i kendi dizinlerine kopyalamak zorunda kalacak, bu da en azından yer israfı..Net in en önemli ve, Com’a göre en üstün olduğu noktalardan birisi de kaynak paylaşımında son derece esnek bir versiyon politikasına sahip olması. Ancak private assembly’ler her ne kadar, oldukça faydalı bir çözüm olsa bile versiyon politikası yönünden bazı eksiklileri var. Biraz daha açarsak, biz dll’imiz için 2. bir versiyon yazar, ve yeni özellikler eklersek, kuşkusuz bir çok programcı gibi  biz de , bu 2 . versiyonu kullanmak isteriz. İyi ama bu 2. versiyonda istemeden ilk versiyondaki bir özelliği ortadan kaldırdıysak o zaman ne olacak ? Eğer paylaşılan bir kaynağı yönetmek için sağlam bir çözüm bulamazsak, o zaman  birinci versiyon ile yazılan programlar ikinciye geçemeyecek .Sorunlar daha da detaylandırılabilir, ancak uzun lafın kısası, private assembly’ler bazı durumlarda yeterli değil. İşte bu noktada, ek birkaç özellikle ile karşımıza shared assembly kavramı çıkıyor. Şimdi hemen hemen her örnekte gördüğümüz System namespace’ini düşünün, içinde Console.Writeline geçen tüm satırlar bu namespace’i kullanıyor. Peki ama biz programlarımızı derlerken bu namespace için bir dll’e referans verdik mi ? Hayır ! Ama bu kaynak bir shared assembly olarak tasarlandığı için,  sistemde kendisini çağıran her uygulamaya otomatik olarak içerdiği  kaynakları kullanması için  izin veriyor. Bir private assemly ile global (veya public yada shared) assembly arasında teknik olarak bir çok ortak nokta var, ancak global assemblylerin en önemli özelliği, bir bilgisayarda bulunan birden fazla yazılımın kullanabilmesi için tasarlanmış olmaları. Private assemblyler verdiğimiz örneklerde de gördüğünüz gibi, kendilerini kullanan uygulamanın alt dizinlerinden birinde yer alıyordu. Genelde bir global assembly için bu durum geçerli değildir.Shared assemblyler genelde Global Assembly Cche denilen bir yerde bulunurlar.Bundan sonra GAC olarak hitap edeceğimiz bu dizin, hardiskinizde WinNTAssembly altdizini altında yer alır. Lütfen şimdi bu dizine gidip bir bakın, en azından içinde neler var bir göz atın, ben sizi bekliyorum :)Com ile .NET arasında bir başka fark da, burada ortaya çıkıyor. COM ile çalışırken Registryde gerekli bilgiler hazırlandıktan sonra, paylaşılan kaynaklar herhangi bir dizine atılırdı, oysa .NET ile çalışırken, daha derli toplu bir yöntem izliyoruz, ve GACı kullanıyoruz. Doğal olarak , birden fazla yazılım tarafından kullanılmaları gerektiği için shared assemblyler için bir takım özel mekanizmaların kullanılması gerekiyor. Bunların en önemlilerinden biri de versiyon bilgisi. .NET altında ortak olarak kullanılan bir assembly ile çalışacaksanız, onu kullanmadan önce mutlaka, versiyon bilgisini belirtmeniz gerekiyor. .NET in bu konudaki hassasiyeti, onun bizlere sağladığı bir olanaktan kaynaklanıyor: daha önce de bahsettiğimiz gibi , .net ile çalışırken, aynı assemblynin değişik versiyonları aynı bilgisayarda bulunabiliyor.Bu nedenle siz hangi versiyonu kullanmanız gerektiğini belirtmelisiniz.Versiyon bilgisinin yanısıra, shared assemblyler "strong/shared name" diye tabir edilen global bir isme de sahip oluyorlar.   Şimdi isterseniz bu "shared name" özelliğinde ne gibi bilgiler bulunuyor, buna bir bakalım:

* Kolayca tanımlanabilecek bir isim (benimdllim gibi )

* Bir versiyon bilgisi

* Bir public/private anahtar ikilisi

* Dijital bir imza

Şimdi burada işler bir parça karışmaya başladı değil mi ? Haklısınız, bu anahtar kavramı da nereden çıktı ?? Anahtarlar, bizim shared olarak hazırladığımız her assembly için bir zorunluluk, çünkü bizim hazırladığımız assemblynin tamamen kendine özgü olmasını sağlıyorlar. Kendine özgü olmaktan kastımız, başka hiçbir yazılım bileşeni ile karışmayacak şekilde tanımlanabilmesi. Fazla kafa karıştırmayacak bir şekilde özetlemeye çalışalım. Bir global assembly üretebilmek için, hem public, hem de private keyi kullanmanız gerekiyor. Ancak bu şekilde üretilmiş bir assemblyi kullanmak isterseniz , sadece public key yeterli, ve public key de zaten assembly manifest içinde bulunuyor. O zaman private key ne işe yarıyor ? Private key, bir assemblynin yeni versiyonlarını sadece bir kişinin oluşturmasını garantiliyor. Yani elinde private key olmayan birisi A assemblysinin yeni bir versiyonunu oluşturamaz. Bu sayede, siz diyelim 1.0 versiyonunu kullandığınız , ve sistem güvenliği açısından güvendiğiniz bir assemblynin 2.0 versiyonunu kullanmaya başlarsanız, bu ikinci versiyonun da birinci versiyonu hazırlayan kişiler tarafından hazırlandığına emin olabilirsiniz. Başka bir değişle, public assemblysi aynı bile olsa private assemblyleri ayrı olan iki assembly .NET runtime tarafından farklı olarak kabul edilirler. Bütün bu mekanizmanın amacı, sizin yazılımlarınızı son derece kesin bir metodla imzalayabilmenizi sağlamak. Birazdan bazı örnekler ile üzerinde çalışınca bu konuyu  daha rahat Kavrayabileceğiz diye umuyorum.Diyelim ki bundan önceki örneklerimizde oluşturduğumuz private assemblyi bir shared assembly olarak oluşturacağız. Bu durumda ne olacak peki ? Eğer her şey yolunda giderse, bu dll içindeki kaynaklar sistemde kolayca erişilebilir bir hale gelecek.Eh, madem ne yapacağımıza karar verdik, o zaman biraz daha somut bir şeyler yapalım. İlk olarak şu bahsedip durduğumuz anahtarlara ihtiyacımız olacak, ne de olsa onlar sayesinde dll’imize imza atacağız . Dijital bir anahtarı köşedeki anahtarcıdan alamayacağımıza göre, .NET Framework ile gelen araçlardan birisi olan “sn.exe” yi kullanacağız. Command prompt’da :C:>Sn –k c:anahtar.snkYazdığımız anda, belittiğimiz yerde anahtar.snk dosyası oluşacak ve bu dosyada bizim public ve private keylerimiz bulunacak. Burada eklemeden geçmek istemedim, eğer kullandığım bir komut sizin bilgisayarınızda kullanıldığında tanınmıyorsa, büyük ihtimalle sorun path dediğimiz işletim sistemi değişkeninin sizin kullanmak istediğiniz komuta göre tanımlanmamış olmasıdır.Bu durumda find ile dosyanın yerini bulduktan sonra, command promptan tam yerini yazarak komutu çağırın, ve en temizi o konumu path değişkeninize ekleyin. Şimdi isterseniz, bu yazı dizisinde daha önce yaratmış olduğumuz dll’imize geri dönelim. Bu dll ’in kaynak kodunda tek bir satır bile değiştirmeyeceğiz. Biraz düşünürseniz, bunun için bir neden de yok, bizim yapmak istediğimiz şey, önceden sadece kendisine ihtiyaç duyan uygulamalar ile aynı dizinde, veya uygulamanın alt dizinlerinden birinde bulunması gereken bu dll’i GAC (global Assembly Cache ) içine yerleştirmek. GAC içine ise sadece global assembly ‘ler yerleştirilebilir. Yani bu dll ’i GAC içine yerleştireceğiz, ve sistemdeki tüm programlar ona erişebilecekler. Peki, bunun için neler yapmalıyız, bir hatırlayalım: 1)      Önce bir public - private key ikilisine ihtiyacımız var. Bunu da sn.exe ile oluşturduk. ( Anahtar.snk)

2)      Daha sonra, bu oluşturduğumuz anahtar ile dll imizi imzalayacağız ve böylece GAC a yerleşmeye hak kazanmış bir DLL imiz olacak.

3)      Eh, madem elimizde un var, yağ var, o zaman biz de helvamızı yapıp, son aşamada bu dlli GACa yerleştireceğiz.

Burada anlatılan konuyu ve yaptığımız çalışmayı tam anlamıyla kavrayabilmek için, önce c: altında temiz bir çalışma dizini oluşturalım ve adını GLOBAL olarak belirleyelim. Bundan sonraki komutları da global dizinini kullanarak yazacağım, kendi sisteminizde bu komutları c yerine başka bir partisyon veya hd kullanarak yazabilirsiniz ( D, E, ....). Şimdi işleri biraz derli toplu ve takip edilebilir bir şekilde yürütmeye çalışalım, ve önce elimizdeki malzemelere bakalım. Önce dllimizin kaynak kodunu görelim://globaldll.cs

 

using System;

namespace sharedones

{

       public class container

       {

             public int member1;

             public string member2;

             public container()

             {

             this.member1=10;

             this.member2="Ben bir public elemanim!";

             }

       }

}

//globaldll.cs bitti

 

Güzel, şimdi de bu dlli kullanacak uygulamanın kaynak koduna bakalım:

//globalclient.cs

using System;

using sharedones;

namespace clientapp

{

      public class clientclass

      {

      public container mycontainer;

      public clientclass()

            {

            this.mycontainer=new container();

            }

      }

      public class mainone

      {

      public static void Main()

      {

      clientclass myclient=new clientclass();

      Console.WriteLine(myclient.mycontainer.member2);

      }

      }

}

//globalclient.cs bitti

Şimdi burada daha önce bahsi geçmeyen bir başka C# dosyası göreceğiz,  o da anahtar.cs :

//anahtar.cs

using System.Reflection;

using System.Runtime.CompilerServices;

[assembly: AssemblyKeyFile("anahtar.snk")]

//anahtar.cs bitti

Peki bu anahtar.cs nereden çıktı ? Ne işe yarıyor ? Bu dosyanın görevi, oluşturduğumuz anahtarların nerede olduğunu C# derleyicisine bildirmek. Bu dosyayı da DLL in kaynak kodu  ile birlikte derleyiciye gönderdiğimiz zaman elimizde imzalanmış bir dll olacak. Bu da bu dll GAC da yer alması için gereken şart.

Komut satırında çalışmaya başlamadan önce biraz daha somut olması için bir diyagram üzerinde tekrarlayalım:

ve şimdi derleme komutunu verelim . Eğer PATH environment değişkeniniz C# derleyicinizin yerini içerecek şekilde ayarlandıysa direk komut satırında bu komutu yazabilirsiniz. Yok durum bu değilse csc.exe nin bulunduğu yere CD ile geçtikten sonra komutumuzu çalıştırıyoruz:

C:>csc /t:library /out:c:globalglobaldll.dll  c:globalglobaldll.cs c:globalanahtar.cs

Bu komut ile birlikte, bir anahtar ile imzalanmış bir dllimiz oldu. Şimdi bu dlli nasıl GACa koyacağız ? Ben tutup bunu olduğu gibi GAC altına atsam ne olur diyenler için : gayet güzel olur! İşin aslı dll imiz gerekli şartları sağladığı sürece bu şekilde yerleştirebiliriz. Ancak biz daha bir programcı metodunu tercih edeceğiz, ve bu iş için gacutil.exe isimli bir başka aracı kullanacağız.

(gacutil.exe Global Assembly Cache Utility anlamına geliyor )

C:>gacutil /i c:globalglobaldll.dll

Microsoft (R) .NET Global Assembly Cache Utility.  Version 1.0.2914.16

Copyright (C) Microsoft Corp. 1998-2001. All rights reserved.

Assembly successfully added to the cache

İşte komutumuz ve çıktısı. Assembly başarı ile eklendi !!

Yukarıda yazdığımız adımların tamamını gerçekleştirdik. Artık elimizde tüm sistemden çağrılabilecek bir dll var. Hemen bu dll i kullanan bir program yazalım, ve bu yeni tanıştığımız mekanizmayı test edelim. Burada da geçen yazılarda kullandığımız uygulamayı kullanacağız. Yani istemcimizin kaynak kodunda da bir değişiklik yok.

//globalclient.cs

using System;

using sharedones;

namespace clientapp

{

      public class clientclass

      {

      public container mycontainer;

      public clientclass()

            {

            this.mycontainer=new container();

            }

      }

      public class mainone

      {

      public static void Main()

      {

      clientclass myclient=new clientclass();

      Console.WriteLine(myclient.mycontainer.member2);

      }

      }

}

//globalclient.cs bitti

Şimdi biraz merakımızı uyandırabilecek denemeler yapalım, ve global altındaki globaldll.dll i bir başka yere taşıyalım. İlk başta istemcimizi komut satırında globaldll.dll e bir referans vermeden derleyelim, bakalım ne olacak :C:>csc /t:exe  /out:c:globalglobalclient.exe  c:globalglobalclient.cs

Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914]

Copyright (C) Microsoft Corp 2000-2001. All rights reserved.

globalglobalclient.cs(4,7): error CS0246: The type or namespace name

        sharedones could not be found (are you missing a using directive or an

        assembly reference?)

globalglobalclient.cs(11,9): error CS0246: The type or namespace name

        container could not be found (are you missing a using directive or an

        assembly reference?)

Hmm, demek ki global bir dll bile olsa, bu C# derleyicisinin onu şıp diye bulabileceği anlamına gelmiyor. Yani derleme sırasında yine referans olarak dllin bir kopyasına işaret etmeliyiz.Eh,  o zaman dlli tekrar global dizini altına alalım ve tam teşekküllü bir derleme komutu verelim :C:>csc /t:exe  /out:c:globalglobalclient.exe /reference:c:globalglobaldll.dll  c:globalglobalclient.cs

Şimdi oldu...

Artık heyecan verici aşamaya geldik, komut satırına :

C:>c:globalglobalclient.exe

Girdiğimizde :

Ben bir public elemanim!

Çıktısını alıyoruz.

İyi hoş da, biz bu işi private assembly ile de yapıyorduk, ne anlamı var şimdi bu kadar uğraşmamızın diyebilirsiniz, hatta konuyu yeterince sıkı takip ettiyseniz demeniz gerekir. O zaman global dizini altındaki globaldll.dll oradan başka bir yere taşıyın, veya en iyisi silin !!! Sonra tekrar programı çalıştırın:Program yine çalıştı!!! Yani buradan ne anlıyoruz  ? Programımız artık bir global assembly içindeki bir kaynağı kullandığı için, bu kaynağı içeren assembly, artık otomatik olarak bulunabiliyor. Bu durumda neler olduğunu tekrar bir diyagramla inceleyelim :

Evet, şimdi şu anda bulunduğumuz noktaya bir bakalım: .NET altında kaynakların paylaşımına dair oldukça yeterli bir temel bilgimiz var, mekanizmanın nasıl çalıştığını biliyoruz, private ve shared assembly leri de biliyoruz..

Eh hiç de az sayılmaz. Bu yazıyı daha fazla kafa karıştırıcı olmaması açısından burada bitirsek iyi olur. Bundan sonraki yazıda global assemblyler ve versiyon kullanımına gireceğiz, ancak bu notaya kadar aklınıza yatmayan bir şey varsa, tam olarak kavramadan daha ilerisi ile uğraşmamanızı tavsiye ediyorum, zira eksik bir altyapı ile işin içinden çıkmak hayli zor olur.

Bir sonraki makalede görüşene kadar , kendinize iyi bakın :)

Döküman Arama

Başlık :

Kapat