Silverlight 3.0 ile Assembly Caching

0 dakikada yazıldı

6297 defa okundu

Düzenle

Silverlight uygulamalarınızda harici kontroller kullanmamak elde değil.
Bugün ister Silverlight SDK ile beraber gelen kontroller olsun ister
Silverlight Toolkit ile beraber gelenler hepsi de neredeyse hayati öneme
sahip. Tüm bu senaryoda XAP dosyamızın büyüklüğünü olabildiğince ufak
tutmak da tabi bir diğer hedefimiz. Bu çerçevede zaten hali hazırdaki
çoğu kontrol de ayrı kütüphanalere saklanmış durumda. Örneğin
Silverlight SDK ile beraber gelen ve Visual Studio içerisinde varsayılan
yüklemelerle Toolbox'a yerleşen DataGrid aslında harici bir DLL
içerisinde bulunuyor. Siz herhangi bir şekilde uygulamanıza DataGrid
eklediğinizde akraplanda söz konusu DLL de projenize eklenmiş oluyor.
Tabi bu durum gün geçtikçe XAP dosyanızın şişmesine neden olabiliyor
çünkü malum, kullandığınız tüm DLL'lerin XAP'ın içerisinde
yerleştirilmek durumunda.

Yazıma böyle uzun ve konumuzla alakası pek de belli olmayan bir yazıyla
başlamamın emin olun bir nedeni var :) Konumuz olan "Assembly Caching"
aslında da tam bir önceki parafragta bahsettiğimiz sorunları kısmen de
olsa çözmeyi planlıyor. Sonuçta eğer DataGrid kullanacaksanız DLL'ini
istemciye göndermek zorundayız, bunu engelleyemeyiz fakat nasıl
gönderileceği ile ilgili belki bazı değişiklikler yapabiliriz...

Yeni  bir proje yeni bir hayat....

Şimdi gelin Visual Studio'da yeni bir Silverlight projesi yaratalım ve
araç çubuğundan bir DataGrid tutup hemen sahneye atın. Bu işlemi
yapmanızla beraber XAML tarafında DataGrid için gerekli namespace'lerin
tanımlandığını ve bazı DLL'lerin otomatik olarak referans alındığını
göreceksiniz. Hemen başka kod yazmadan projenizi Build ederek XAP
dosyasının da uzantısını değiştirip ZIP yapıp içerisine bir göz atalım.

DataGrid ile normal bir Silverlight projesi.
DataGrid ile normal bir Silverlight projesi.

Yukarıdaki gördüğünüz üzere bir DataGrid için toplam 4 ayrı DLL XAP
dosyasına eklenmiş durumda. Özellikle DataGrid'in kendisinin bulunduğu
DLL 430KB. Tabi tüm bunlar XAP içerisinde ZIP'lendiği için daha ufalıyor
fakat şu anda bile XAP dosyamızın büyüklüğü 206KB. Bu arada
assembly_caching_VB.dll dosyası kafanızı karıştırmasın, benim yaratmış
olduğum örnek projenin adı assembly_Caching_VB olduğu için aslında o
dosya projemizin kendi kodlarını içeriyor.

Peki ne yapabiliriz?

Daha önce de dediğim gibi sonuçta bu DLL'lerin istemciye gitmesi şart.
Yapabileceğimiz tek şey uygulamadan bağımsız olarak bu DLL'lerin istemci
tarafında önbelleklenebilmesini sağlamak. Genelde bu şekilde uygulama
geliştirirken uygulamanız sürekli değişebilir fakat kullandığınız hazır
kütüphanaler genelde hep aynıdır. Yani bizim DataGrid olan uygulamamız
değişse ve cachlenmese de aslında DataGrid'in kendisinin bulunduğu DLL
rahatlıkla daha uzun vadeli olarak cachelenebilir.

Tabi bu gibi bir Cachelemenin tarayıcı tarafından yapılabilmesi için bu
DLL'lerin ayrı paketler olarak istemciye gönderilmesi gerekiyor. Bu gibi
bir senaryoyu kendi kodlarımızı yazarak oluşturabiliriz fakat
Silverlight 3.0 ile beraber gelen Assembly Caching mekanizması zaten
bunu yapıyor. O nedenle pek de kod yazmadan hemen işimizi
halledebiliriz.

Silverlight projenize sağ tuş ile tıklayarak gelen menüden "Properties"
komutunu verip karşınıza çıkan ekranda "Reduce XAP Size..."
seçeneğini işaretleyebilirsiniz.

Assembly Caching'i aktif hale getiriyoruz.
Assembly Caching'i aktif hale getiriyoruz.

Hemen projemizi yeni build edip ASP.NET projemizdeki ClientBin klasörü
içerisine bir göz atalım. Artık ClientBin içerisinde XAP dosyamızın yanı
sıra ayrı ZIP dosyaları da bulunuyor. Bu dosyalar bir önceki adımda XAP
dosyası içerisindeki DLL'lerin ZIP'lenmiş halleri. Anlayacağınız söz
konusu DLL'ler artık XAP içerisinde değiller ve XAP dosyamız 5KB'a
düşmüş durumda. DLL'ler harici ZIP'ler şeklinde paketlenerek XAP ile
aynı konuma yerleştirilmiş.

Assembly'ler ayrı ZIP'lerde...
Assembly'ler ayrı ZIP'lerde...

Ne fark etti derseniz aslında konu çok basit. Yukarıdaki şekli ile
DLL'ler ayrıldığında yazılımcıların bu DLL'leri ayrı ayrı update etme
şansı oluyor. Sonuç olarak sunucu tarafındaki HTTP Header'a
LastModifiedDate'e bakacak olan tarayıcı taraflı cachleme mekanizmaları
uygulama değişmiş olsa da DLL'leri içerisinde ZIP'ler değişmemişse
DLL'lere ait ZIP'leri indirmeyecek ve önbellektekini kullanacaktır. Bu
durum da tabi ki performansta ciddi bir artış yaratır.

[AppManifest.xaml / Assembly Caching Öncesi]

<Deployment
xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="assembly_caching_VB" EntryPointType="assembly_caching_VB.App" RuntimeVersion="3.0.40624.0">

  <Deployment.Parts>

    <AssemblyPart
x:Name="assembly_caching_VB" Source="assembly_caching_VB.dll" />

    <AssemblyPart
x:Name="System.ComponentModel.DataAnnotations" Source="System.ComponentModel.DataAnnotations.dll" />

    <AssemblyPart
x:Name="System.Windows.Controls.Data" Source="System.Windows.Controls.Data.dll" />

    <AssemblyPart
x:Name="System.Windows.Controls.Data.Input" Source="System.Windows.Controls.Data.Input.dll" />

    <AssemblyPart
x:Name="System.Windows.Data" Source="System.Windows.Data.dll" />

  </Deployment.Parts>

</Deployment>

[AppManifest.xaml / Assembly Caching Sonrası]

<Deployment
xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="assembly_caching_VB" EntryPointType="assembly_caching_VB.App" RuntimeVersion="3.0.40624.0">

  <Deployment.Parts>

    <AssemblyPart
x:Name="assembly_caching_VB" Source="assembly_caching_VB.dll" />

  </Deployment.Parts>

  <Deployment.ExternalParts>

    <ExtensionPart
Source="System.ComponentModel.DataAnnotations.zip" />

    <ExtensionPart
Source="System.Windows.Controls.Data.zip" />

    <ExtensionPart
Source="System.Windows.Controls.Data.Input.zip" />

    <ExtensionPart
Source="System.Windows.Data.zip" />

  </Deployment.ExternalParts>

</Deployment>

Bildiğiniz üzere her XAP dosyası içerisinde Assembly'lerin adreslerini
tutan birer de Manifest dosyası bulunuyor. Bu manifest dosyalarına dair
birer örneği yukarıda inceleyebilirisniz. Assembly Caching aktif
hale getirildikten sonra artık Assembly'lerin birer ExtensionPart
olarak geçtiğini ve uygun ZIP dosyalarının adreslerinin de Source olarak
verilmiş olduğunu görebiliyoruz.

Ya Kendi Kütüphanalerimiz?

Dikkat ettiyseniz yukarıdaki kütüphanalerin hepsi de Microsoft
kütüphanaleriydi. Aynı sistemi kullanarak Silverlight projenize kendi
yarattığınız bir kütüphaneyi referans alırsanız Assembly Caching aktif
olsa da DLL'inizin yine XAP dosyası içerisine yerleştirildiğini
göreceksiniz. Gelin bu durumu nasıl değiştirebileceğimize göz atalım.

İlk olarak ileriki aşamalarda Assembly'miz ile ilgili bir Public Key
Token
'a ihtiyacıımz olacağı için Assembly'mizin Strong Name'e
ihtiyacı var. Bunun için Silverlight ile aynı Solution içerisine
eklediğimizi varsaydığım örnek "Silverlight Class Library" projesine sağ
tuş ile tıklayarak gelen menüden "Properties" komutunu verip "Signing"
tabına geçmemiz gerekiyor.

Assembly'miz Strong Name ekliyoruz.
Assembly'miz Strong Name ekliyoruz.

Uygun bir "Key File Name" verip yaratacağınız key dosyasını seçerek bu
işlemi tamamlayabilirsiniz. Daha önce de bahsettiğim üzere bize esas
lazım olan Public Key Token olacak. Söz konusu key'i alabilmek için
Class Library'i build ettikten sonra .NET Framework SDK ile beraber
gelen Strong Name Utility'yi kullanmamız şart. Visual Studio ile
beraber yüklenen "Visual Studio 2008 Commant Prompt"u başlat menüsünden
bulup çalıştırdıktan sonra sn -Tp Assembly Adı şeklinde gerekli
komutu çalıştırabilirsiniz.

Bize "Public Key Token" lazım!
Bize "Public Key Token" lazım!

Şimdi aldığımız bu Token ile aşağıdaki formatta bir XML dosyası yaratıp
DLL'imiz ile aynı yere yani bin klasöründe Release altına koymalıyız.

[OrnekLibrary_VB.extmap.xml]

<?xml
version="1.0"?>

<manifest
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

          xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <assembly>

    <name>OrnekLibrary_VB</name>

    <version>1.0.0.0</version>

    <publickeytoken>266fe0f58a4900bb</publickeytoken>

    <relpath>OrnekLibrary_VB.dll</relpath>

    <extension
downloadUri="OrnekLibrary_VB.zip" />

  </assembly>

</manifest>

Gördüğünüz üzere dosya içerisinde DLL'in adı, sürüm numarası, Assembly
adı ve Token bulunuyor. Ayrıca extension tagına ait downloadUri
özelliğinde de dosyanın adresini veriyoruz. Adres kısmında eğer
yukarıdaki şekilde bir dosya adı verirseniz Visual Studio sizin adınızda
DLL'i söz konusu dosya adı ile ZIP'ler ve ClientBin içerisinde
yerleştirir. İsterseniz downloadUri'ye harici bir adres de
verebilirsiniz. Hatta bu adres XAP'ın bulunduğu alan adı haricinde de
olabilir. Böyle bir durumda Visual Studio ZIP üretmeyecektir. Unutmayın
harici bir alan adında caching yapacaksanız kesinlikle o alan adında ZIP
dosyaları için uygun ClientAccessPolicy.xml dosyalarının da oluşturulmuş
olması gerekir, aksi halde cross-domain-request yapılamaz.

Dosyamız hazır olduğuna göre onu DLL ile aynı yere kaydedebilirsiniz.
Kaydederken Assembly Adı ve sonrasında da extmap.xml yazmanız şart.

Artık herşeyimiz hazır olduğuna göre Silverlight projemizi build
edebiliriz. ClientBin içerisinde DLL'inizi ayrıca ZIPlenmiş olarak
göreceksiniz!

Neden kullanayım?

Assembly Caching kullanmak uygulamanızın açılışını hızlandırmaz. Eğer
hedef makinede daha önce uygulama açılmamış ise yine tüm kütüphanaler
indirileceği için birşey değişmeyecektir. Fakat ikinci ve sonraki
açılışlarda tarayıcı harici kütüphanaleri cachlediği için uygulamanız
değişse de çok daha hızlı açılacaktır. Siz reference DLL'leri
değiştirmedikçe ve harici kütüphanalere dair dosyalar yenilenmedikçe
cacheleme tarayıcı tarafından yapılacaktır.

Özellikle harici bir alan adında kütüphaneleri önbelleklemek belki de
aynı kütüphanaleri farklı uygulamalarda kullananlar için uygun olabilir.
Böylece merkezi bir yönetim de kısmen sağlanmış olacaktır. Tüm bunları
yaparken de ek kod yazmak zorunda kalmamak güzel bir avantaj olsa gerek.

Hepinize kolay gelsin!

Dikkat: Assembly Caching Silverlight 3 Beta iken çok daha farklı
çalışıyordu. Bu konuda internette bir araştırma yaptığınızda
karşılaşacağınız kaynakların çoğu size Assembly Caching'in sadece MS
kütüphanaleri için yapılabileceğini ve kütüphanalerin MS tarafından host
edildiğini söylemeyebilir. Silverlight 3 Beta'yken durum böyleydi  fakat
artık değil. MS kütüphanaleri dahil olmak üzere hostingi sizin yapmanız
gerekiyor ayrıca yukarıda da gördüğünüz üzere kendi kütüphanalerinizde
de bu özelliği kullanabiliyorsunuz.

Örneğe ait kaynak kodlar - 15082009_6.rar (986,18
KB)