Silverlight 2.0 içerisinde harici Class Library yapılarının asenkron kullanımı.

0 dakikada yazıldı

6493 defa okundu

Düzenle

Silverlight projeleriniz büyüdükçe projenin bazı bölümlerini sonradan
istemci tarafına aktarmayı daha uygun bir seçenek olarak görebilirsiniz.
Bu gibi durumlarda acaba ayrı bir XAP dosyası yapsak da onu haricen
istemciye yüklesek diye düşünürseniz maalesef söz konusu XAP dosyasını
kendi kodlarınız ile ZIP şeklinde açmanız ve içerisindeki Manifest.xml'i
yine kendi kodunuz ile okuyup tek tek DLL'leri yüklemeniz gerekecektir.
Bu konuda detaylı bir makaleye
buradan
ulaşabilirsiniz.

Bu zorluklarla uğraşmadan hızlı bir şekilde belki de sadece bir
UserControl'ü haricen sonradan yüklemek istiyorsanız aslında çok daha
pratik ve hızlı bir yöntem de kullanılabilir. Bu yönteme sadece
UserControl'ler değil harici olarak yazılan sınıflar da dahil. Gelin
daha fazla teorik konuşma yerine bir örnek üzerinden ilerleyelim.

Haricen yüklenecek içeriği hazırlayalım....

İlk olarak ana Silverlight uygulamamıza sonradan yüklenecek olan içeriği
hazırlayalım. Bunun için Visual Studio içerisinde "File / New Project"
dedikten sonra "Silverlight" seçeneği altındaki "Silverlight Class
Library
" proje tipini seçiyoruz. Bu proje tipinde doğrudan tüm proje
içeriği bir DLL içerisine konacak fakat bu DLL ayrıca bir XAP dosyası
içerisinde sıkıştırılmayacak. Böylece biz de Silverlight ile istemci
tarafında bir XAP dosyası açmak veya Manifest ile uğraşmak zorunda
kalmayacağız.

Normal şartlarda Silverlight Class Library projesi yarattığınızda proje
içerisinde sadece bir CS veya VB dosyası görebilirsiniz. Oysa bu
projelere de isterseniz XAML dosyaları ile beraber UserControl'ler
eklenebilir. Projenize sağ tuş tıklayarak Solution Explorer içerisinden
"Add New Item" demeniz ve gelen seçeneklerden de "Silverlight User
Control"ü seçmeniz yeterli olacaktır. Artık isterseniz bu projeyi Blend
içerisinde de açıp normal bir Silverlight projesindeki gibi animasyonlar
vs kullanabilirsiniz.

Örnek olarak projemize bir resim dosyası ekleyerek UserControl'ümüz
içerisinde de onu gösterebilir. Unutmayın ki resim dosyasını projeye
"Add Existing Item" diyerek eklerseniz artık bu resim de DLL'inizin
içerisine dahil edilecektir.

[XAML]

<UserControl
x
:Class="SilverlightClassLibrary1.SilverlightControl1"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400"
Height
="300">

    <Grid
x
:Name="LayoutRoot"
Background
="White">

        <Image
Margin
="71,47,97,122" Source="Forest.jpg"/>

    </Grid>

</UserControl>

Yukarıdaki şekli ile UserControl'ümüz hazır olduktan sonra projemizi
Build ederek DLL'imizi yaratmış oluyoruz. Bu DLL'i bir sonraki adımda
yaratacağımız Silverlight projesinin XAP dosyası ile aynı konuma
koyabilirsiniz. Silverlight projemiz içerisinden bu DLL'i istemciye
asenkron olarak download ederek sahneye DLL içerisindeki UserControl'ü
yükleyeceğiz.

Gelelim Silverlight projemize...

Tertemiz bir Silverlight projesi yarattıktan sonra proje ile beraber
gelen ASP.NET sitesi içerisinde ClientBin klasörüne bir önceki adımda
yarattığımız DLL dosyasını kopyalayalım. Böylece projeyi Build ettiğimiz
aynı konuma otomatik olarak kopyalanacak olan XAP dosyası üzerinden
DLL'e de rahatlıkla ulaşabiliriz.

Yeni Silverlight projemizin ana Page.XAML dosyasına bir Button ve bir de
Canvas ekleyelim. Böylece düğmeye basıldığında harici DLL'i yükleyecek
ve DLL içerisindeki UserControl'ümüzü de Canvas içerisine
yerleştireceğiz.

[XAML]

<UserControl
x
:Class="SilverlightApplication5.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400"
Height
="300">

    <Grid
x
:Name="LayoutRoot"
Background
="White">

        <Button
x
:Name="btnTikla"
Height
="19" HorizontalAlignment="Right"
Margin
="0,0,18,17" VerticalAlignment="Bottom"
Width
="89" Content="Button"/>

        <Canvas
x
:Name="Icerik"
Margin
="13,13,18,54"/>

    </Grid>

</UserControl>

Düğmeye tıklandığı anda hemen bir WebClient yaratarak download
işlemimizi başlatalım.

[VB]

Private BirAssembly As System.Reflection.Assembly

 

Public Sub New()

    InitializeComponent()

    AddHandler Me.btnTikla.Click, AddressOf btnTikla_Click

End Sub

 

Private Sub btnTikla_Click(ByVal sender As Object,
ByVal e As RoutedEventArgs)

    Dim Yukleyici As New
WebClient()

    AddHandler
Yukleyici.OpenReadCompleted, AddressOf
Yukleyici_OpenReadCompleted

    Dim Yol As String

System.Windows.Application.Current.Host.Source.AbsoluteUri.Replace("SilverlightApplication5.xap", "SilverlightClassLibrary1.dll")

    Yukleyici.OpenReadAsync(New
Uri(Yol, UriKind.Absolute))

End Sub

[C#]

        System.Reflection.Assembly
BirAssembly;

 

        public Page()

        {

            InitializeComponent();

            this.btnTikla.Click +=
new RoutedEventHandler(btnTikla_Click);

        }

 

        void btnTikla_Click(object sender, RoutedEventArgs e)

        {

            WebClient Yukleyici =
new WebClient();

            Yukleyici.OpenReadCompleted += new OpenReadCompletedEventHandler(Yukleyici_OpenReadCompleted);

            string Yol =
System.Windows.Application.Current.Host.Source.AbsoluteUri.Replace("SilverlightApplication5.xap", "SilverlightClassLibrary1.dll");

            Yukleyici.OpenReadAsync(new Uri(Yol, UriKind.Absolute));

        }

Yukarıdaki kodu dikkatli incelemek gerekirse ilk adımda en üstteki
Assembly tipindeki BirAssembly adındaki değişkenimizi açıklamak
gerekecek. Kodumuz sunucudan bir DLL indirecek ve içindeki UserControl'ü
sahneye koyacak. Aslında DLL'i indirdikten sonra içerisinden
UserControl1 sınıfından bir instance alarak sahneye koyacağız. Eğer bu
işlemi yaptıktan sonra başka instance'lara da ihtiyacımız olursa tekrar
DLL'i indirmemek için eldeki Assembly'yi bir değişken olarak tutmak daha
mantıklı olacaktır. O nedenle en üstteki BirAssembly değişkenimiz
şimdiden yerini almış durumda.

Button'umuzun Click koduna baktığımızda bir WebClient yarattığımızı ve
OpenReadCompleted event listener'ını da başka bir koda bağladığımızı
görebilirsiniz. Sunucudan bir dosya indireceği ve indirme işlemi
bittiğinde de başka işler yapacağız. O nedenle bu event'ları
yakalayabiliyor olmak çok önemli. İsteyenler WebClient'ın
DownloadProgressChanged event'ını da yakalayarak download durumu ile
ilgili yüzde üzerinden ne kadarının indirildiğine dair bilgileri de
ekranda gösterebilirler.

Sunucudan indireceğimiz dosyanın tam yolunu verebilmek için şu anki XAP
dosyasının tam yolunu alıp sadece dosya adını değiştiriyoruz. Bizim
örneğimizde saten her şeyin yeri ve dosya adları belli olduğu için
herhangi bir sorun olmayacaktır.

Son olarak OpenReadAsync metoduna da indirilecek olan dosyanın yolunu
verip download işlemini başlatıyoruz. Peki ya bu işler bitince çalışacak
olan Yukleyici_OpenReadCompleted metodunda neler yapacağız?

[VB]

Private Sub Yukleyici_OpenReadCompleted(ByVal sender As Object,
ByVal e As OpenReadCompletedEventArgs)

    Dim GelenAssembly As New
AssemblyPart()

    BirAssembly = GelenAssembly.Load(e.Result)

    Dim Kontrol As UserControl = DirectCast(BirAssembly.CreateInstance("SilverlightClassLibrary1.SilverlightControl1"),
UserControl)

    Me.Icerik.Children.Add(Kontrol)

End Sub

[C#]

            AssemblyPart
GelenAssembly = new AssemblyPart();

            BirAssembly = GelenAssembly.Load(e.Result);

            UserControl Kontrol =
(UserControl)BirAssembly.CreateInstance("SilverlightClassLibrary1.SilverlightControl1");

            this.Icerik.Children.Add(Kontrol);

Download işlemi bittiği anda bir AssemblyPart değişkeni yaratarak
onun da Load metodunu kullanıyoruz. Load metoduna e.result
ile aslında Yukleyici_OpenReadCompleted event-listener'ına gelen
argüman üzerindeki datayı almış oluyoruz. Yani özünde sunucudan
indirdiğimiz DLL'in Stream'i e.result içerisinde saklanıyor ve biz
de bu AssemblyStream'i doğrudan bir AssemblyPart üzerinden
Load ederek Assembly tipindeki BirAssembly değişkenimize
yüklüyoruz. Hatırlarsanız zaten bu değişkenimiz de global anlamda
sürekli hafızada tuttuğumuz bir değişkendi. Bir sonraki adımda bir
UserControl değişkeni tanımlayarak bunu da Assembly'miz içerisinde
SilverlightControl1'e eşitlememiz gerekiyor.

Assembly üzerinden CreateInstance metodu bizden yaratılacak nesnenin
TypeName'ini istiyor. Silverlight Class Library projesinin içerisindeki
UserControlümüzün tipinin adını full path olarak veriyoruz. Bunu zaten
UserControl'ün XAML dosyasının en üstünden de bulabilirsiniz. Artık
elimizdeki Kontrol değişkeni yine elimizdeki BirAssembly'nin
içerisinden SilverlightControl1'in bir instance'ıdır. Herhangi bir
UserControl gibi bu da alıp sahnede istediğimiz yere yerleştirebiliriz.

Hepinize kolay gelsin.