Delphi 2005 for .NET Compact Framework Technology Preview

Friday, February 22, 2008 12:33:07 PM (GTB Standard Time, UTC+02:00)


Bir Delphi programcısı değilim fakat Mobil Uygulama Geliştiricisi olarak Delphi' ci arkadaşları bilgilendirmek istedim :-)

C#' a geçmem ama Delphi ile .net Compact Framework üzerinde Mobil Cihaz Uygulaması geliştirmek istiyorum diyorsanız Delphi 2005' in .net Compact Framework için derleyicisini incelemenizi tavsiye ederim.

http://downloads.codegear.com/default.aspx?productid=8201

Mobil Cihazlar için Facebook Uygulamaları

Sunday, January 13, 2008 12:00:04 AM (GTB Standard Time, UTC+02:00)

Facebook, facebook, facebook... 7' den 77' sine o herkes için bir fenomen.

Yazılım geliştiriciler perspektifinden bakıldığında facebook için uygulama yazmak gerçekten büyük bir eğlence.

Normal şartlarda kütüphanelerin tümü .Net Framework için geliştirilmişti.

Peki ya .Net Compact Framework ?

Aşağıdaki makaleyi inceleyin derim :-)

http://msdn2.microsoft.com/en-us/library/bb932386.aspx

.Net Compact Framework 2.0 - .Net Compact Framework Assembly’ lerinin GAC’ a Yüklenmesi

Saturday, January 12, 2008 11:51:40 PM (GTB Standard Time, UTC+02:00)

.Net Framework kullanılarak geliştirilen masaüstü Windows uygulamalarında bildiğimiz üzere uygulama geliştiriciler geliştirdikleri uygulamalarının kullandıkları & refere ediyor durumda oldukları .Net Assembly’ lerini işletim sisteminin kök klasörü içerisinde bulunan Assembly klasörü içerisindeki havuzdan kullanabilmektedirler. Daha açık ifade etmek gerekirse Global Assembly Cache ismi ile ifade edebileceğimiz bu merkezcil havuz mekanizması yardımı ile birden çok uygulamanın aynı zaman sürecinde ihtiyaç duydukları assembly’ leri tek bir noktadan kullanılabilmesine olanak sağlayan bu sistem aynı assembly’ nin disk üzerinde defalarca kopyalanması ihtiyacına cevap olmaktadır.

Şekil üzerindende anlaşılabileceği üzere .Net Framework DLL’ lerinin tümü bu merkezcil havuz üzerinde kayıtlı bulunmakta ; bu DLL lere ihtiyaç duyan tüm uygulamalar aynı lokasyon üzerinden DLL’ in kopyasını oluşturmaya gerek duymadan rahatlıkla kullanabilmektedirler.

Global Assembly Cache ; kısa adıyla GAC’ ın sağladığı en mantıklı fayda ise aynı DLL’ in disk üzerinde bu DLL’ i her kullanan uygulama için defalarca tekrar tekrar kopyalanması yerine sunduğu merkezcil yapı olarak ifade edilebilmektedir. Bunun yanı sıra DLL’ in disk üzerinde oluşturulmuş tek bir kopyasının böyle bir havuz içerisinde uygulamala sunulmasının versiyonlama perspektifinden de fayda sağladığı çok açık bir şekilde farkedilebilmektedir.

Fakat günümüzdeki masaüstü bilgisayarlarının donanımsal yeterliliğini göz önünde bulundurduğumuzda disk alanı bakımından aslında çokta sorun yaşanmayacağını ; fakat merkezcillik açısından fayda sağlayacağı açık bir gerçektir.

Bu noktada makalemizinde konusunun temelini oluşturan önemli bir nokta üzerinden yazımıza devam edelim.

Bilindiği üzere uzun yıllardan beri mobil cihazlar üzerinde yaşanan bellek & donanım sıkıntıları uygulama geliştiricilerin başına dert olmaktadırlar. Bu tip cihazlara uygulama geliştiren uygulama geliştiriciler her türlü ihtimali göz önünde bulunduracak şekilde mobil cihaz uygulamalarını geliştirmekte ; yaşanabilecek bellek sıkıntılarının önüne geçebilmek adına ise uygulamalarda gerçekleştirilebildiği kadar kısma işlemine gitmektedirler (Thin Client).

Bu makalemizde ise belki gördüğünüzde “budamı vardı ?” diyebileceğiniz bir konu ile ilgili ; .Net Compact Framework DLL’ lerinin mobil cihazınız üzerinde Global Assembly Cache içerisine kopyalanarak merkezcil bir yapı üzerinden bellek tasarrufunun nasıl sağlanabileceği ile ilgili anlaşılır bir örnek uygulama geliştireceğiz.

Bu noktada konunun daha rahat anlaşılabilmesi açısından teorik ifadelerden öte pratiksel bakımdan çalışmaya hemen başlayalım. Senaryomuz gereği uygulamamız içerisinde basit bir executable uygulama ; bu uygulamanın kullandığıda bir DLL refere olarak kullanılacaktır. Gerçekleştirmek istiyor olduğumuz temel senaryo ise uygulamanın bu DLL’ e lokal lokasyonundan değilde ; mobil cihazımızın işletim sistemi içerisindeki Windows klasörü içerisinden merkezcil olarak ; GAC aracılığıyla erişecek olduğudur.

Hiç vakit kaybetmeden örnek uygulama üzerinde çalışmaya başlayalım. Konu ile ilgili önemli gereksinimler yazı içerisinde detaylı olarak anlatılacaktır.

İlk noktada GACAssembly isminde bir Mobil Cihaz Class Libraryı projesi açıyoruz.

Bu proje içerisine standart olarak eklenen fiziksel cs dosyasının ismini clGAC.cs olarak değiştiriyor ; şekildeki sınıfı fiziksel dosya içerisine ekliyoruz.

Projemizi build ediyoruz ve GAC’ a atılmak üzere geliştiriyor olduğumuz DLL ile ilgili “çok önemli” gerçekleştirmemiz gereken birkaç adım üzerinden uygulamamıza devam ediyoruz.

Bilindiği üzere bir DLL’ in GAC’ a atılabilmesi için gerçekleştirilmesi gereken en önemli adım DLL’ in Strong Name bir DLL olmasıdır. Bu noktada aynı yapı mobil cihazlar üzerindeki sistem içinde geçerlidir.

Mobil cihazlar üzerinde bir DLL’ in cihaz üzerinde GAC’ a gönderilebilmesi için DLL’ in strong name bir DLL olması gerekmektedir. Bu noktada strong name key file üretmek için Visual Studio 2005 Command Prompt penceresi üzerinden :

Şekildeki komutu çalıştırarak c:\Key.snk lokasyonunda bulunacak bir strong name key file oluşturuyoruz. Sıra geldi bu Key file ile DLL’ imizi ilişkilendirmeye. Bu noktada projenin özellikleri içerisinde bulunan Signing sekmesi içerisinde key dosyamızı DLL ile ilişkilendirip projeyi build ediyoruz.

İşte bu kadar ! Konu ile ilgili gerçekleştirilmesi gereken tüm işlemlerin neredeyse hepsi gerçekleştirilmiş durumda.

Sıra geldi test amaçlı geliştirilecek olan mobil cihaz uygulamamıza. Bu uygulama içerisinde senaryo gereği DLL içerisinde tanımlı olan sınıfımızın bir instance’ ı oluşturulacak ; kısaca uygulama bu DLL’ e ihtiyaç duyacak şekilde tasarlanacaktır.

Hiç vakit kaybetmeden mobil cihaz uygulamamızı geliştirmeye başlayalım. İlk noktada standart bir Mobil Cihaz Windows projesi açarak işe başlıyoruz.

Hız kesmeden uygulamamızı geliştirmeye devam ediyoruz. Amaç bir önceki adımda geliştirmiş olduğumuz DLL’ i kullanan standart bir uygulama geliştirmek olacaktır. Bu noktada ilk olarak DLL’ i projemize refere ediyoruz. Dikkat edilecek unsurlardan birisi ise DLL referansının Copy Local özelliğine false değeri verilmiş olduğudur. Bu değer DLL’ in uygulamanın çalıştırılıyor olduğu işletim sisteminin GAC’ ı üzerinden erişileceği anlamına geliyor olmaktadır.

Bir sonraki adımda şekildeki 3 satırlık kod bloğunu uygulama ekranının yüklenmesi esnasında çalıştırılacak şekilde tasarlıyoruz.

Ve bitti ! Uygulamamızı build ediyor ve ilgili adımları gerçekleştirmek üzere makalemize devam ediyoruz.

Bu noktada bir DLL’ in mobil cihazımız üzerindeki GAC’ a atılabilmesi için DLL’ in mobil cihaz üzerinde bir klasöre kopyalanmış olması gerekmektedir. Biz örnek olarak mobil cihazımızın kök klasörü içerisinde bulunan GACFiles isimli bir klasörün içerisine DLL’ imizi kopyalayacak ; bir sonraki adımda ise bu noktadan GAC’ a göndereceğiz.

DLL’ i mobil cihazımız üzerine kopyalamadan önce gerçekleştirmemiz gereken bir diğer önemli adım ise DLL’ in mobil cihaz üzerindeki fiziksel lokasyonunu belirten *.gac uzantılı bir metin dosyası oluşturmamız gerekliliğidir.

Hazırlanan bu dosyayı mobil cihazımız üzerinde bulunan Windows klasörü içerisine kopyalamamız gerekmektedir. Hiç vakir kaybetmeden *.gac uzantılı bu dosyayı oluşturuyor ; içerisine az sonra mobil cihazımız içerisine kopyalayacak olduğumuz DLL’ in adresini tanımlıyoruz.

Dosyayı *.gac uzantısıyla kayıt ediyoruz.

İşte bu kadar ! Sıra geldi üç dosyayı ilgili lokasyonlara kopyalarak GAC’ a kopyalama işini gerçekleştirmeye. Başka bir makalemizde ifade ettiğimiz üzere mobil cihazımız ile paylaşımlı kullanılacak şekilde bir klasörün içerisine EXE, DLL ve GAC Dosyalarını kopyalıyoruz.

Sıra geldi uygulamamızın en heyecanlı noktasına. Bu dosyalara bu klasör ile haberleşebilecek şekilde konfigüre edilmiş bir emülatör yardımıyla erişeceğiz ve sırasıyla şu adımları gerçekleştireceğiz :

Emülatörümüz üzerinde kök dizin içerisinde GACFiles isimli bir klasöre oluşturacak ; GACAssembly isimli DLL’ imizi bu klasörün içerisine kopyalacağız. GACSample.gac isimli dosyamızı Windows klasörü içerisine kopyalayacağız. Ve son olarak GACSample.exe isimli uygulamamızı çalıştırmaya çalışacağız.

.Net Compact Framework lokal lokasyon içerisinde DLL’ i bulamayacağından GAC içerisine bakacak ; ilk istekte bu lokasyondada bulamadığı için *.gac uzantılı dosya içerisinde dosyanın gerçek lokasyonuna erişecek ; ve bu lokasyondan DLL’ i GAC içerisine taşıyacaktır. Hepsi bu kadar !

Hiç vakit kaybetmeden ilgili işlemleri gerçekleştiriyoruz :

Emülatör içerisinde dosyalara erişebilmekteyiz. İlk olarak DLL’ imizi GACFiles isimli kök klasörün içerisine taşıyoruz.

Bir sonraki adımda *.gac dosyamızı Windows klasörü içerisine taşıyoruz :

Ve sıra geldi uygulamamızı çalıştırmaya ! Normal şartlarda uygulama DLL’ i bulamadığı için hata vermesi gerekmektedir. Ama senaryomuz ve yapı gereği DLL GAC içerisinde aranacak ; bulunamadığı durumda ise gerçek lokasyonundan GAC içerisine taşınacaktır. Uygulamamıza tıklayarak çalıştırıyoruz :

Bingo ! Uygulamamız DLL lokal lokasyonda olmamasına rağmen başarılı bir şekilde çalıştırılmıştır. GACFiles içerisine baktığımızda DLL’ in olmadığını rahatlıkla farkedebiliriz :

Çünkü DLL’ imiz .Net Compact Framework tarafından GAC içerisine taşınmıştır :

İşte buda kanıtı !

Bu makalemizde mobil cihazlar üzerinde GAC kullanımına değindik. Başka bir makalede daha görüşmek dileğiyle.

Visual Studio Remote Tools – Remote File Viewer

Saturday, January 12, 2008 11:49:09 PM (GTB Standard Time, UTC+02:00)

Visual Studio 2005 ile birlikte sistemimize Mobil Uygulama Geliştiricilerin hayatını kolaylaştırabilecek bazı “küçük” uygulamalar yüklenmektedir. Bu uygulamalar tamamen izole ve birbirlerinden farklı amaçlar üzerine geliştirilmiş ; Emülatörler ve Fiziksel cihazlar üzerinde çalışabilmektedirler.

Genel hatlarıyla ;

Remote File Viewer

Remote Heap Walker

Remote Process Viewer

Remote Registry Editor

Remote Spy

Remote Zoom In

Şeklinde sıralanabilecek bu küçük uygulamalar normal şartlarda 3rd party uygulamalar kullanılarak yada mobil cihazımızın sınırlı ekranı üzerinden zahmetli bir şekilde gerçekleştirilebilerek yapılan işlemlerde kullanıcılara masaüstü rahatlığı sağlamaktadır. Bu makale serimizde ise liste üzerinde sıraladığımız uygulamalar ile ilgili kısa açıklamalarda bulunacağız.

Şimdiki durağımız Remote Zoom In. RZI genel hatlarıyla uzaktaki bir cihazın ekran görüntüsü almaya – bu görüntüyü yazdırmaya ve kaydetmeye yarayan yardımcı bir uygulama olarak özetlenebilir. Uygulamanın hangi noktalarda kullanılabileceğine gelinirse ; makalelerde, proje sunumlarında, kitap yazarken v.b. gibi süreçlerde mobil cihazımızın anlık ekran görüntüsüne ihtiyaç duyduğumuzda kullanılabilir. Küçük bir örnekle uygulamayı tanımaya başlayalım.

Uygulamamızı Başlat – Programlar – Microsoft Visual Studio 2005 – Visual Studio Remote Tools – Remote Zoom In seçenekleri üzerinden başlatıyoruz. Karşımıza diğer Remote Tools uygulamalarında olduğu gibi hangi mobil cihaz üzerinden bağlantı kurulacağını soran bir seçenek penceresi çıkmaktadır. Bu pencereden daha öncekilerde olduğu gibi aktif bağlı olan Cihaz / Emülatörü seçerek devam ediyoruz.

OK’ e tıkladığımızda uygulama o an aktif bağlantısı olan Cihaz / Emülatörün ekran görüntüsünü almak üzere bir Progress Bar çıkarmaktadır.

İşlem tamamlandığında :

Şekildeki gibi ekran görüntüsünü uygulamamız sistemimize yüklemektedir.Bundan sonra yapılabilecekler menü üzerinden New Bitmap seçeği üzerinden görüntüyü tazelemek olacaktır.

Emülatör üzerinde değişiklik yapıldıktan sonra New Bitmap seçildiğinde Yeni ekran görüntüsü sistemimize kopyalanmaktadır. Kullanıcılar bu görüntüyü File – Print seçenekleri üzerinden Yazdırabilmektedirler.

Ayrıca Save As seçeneği üzerinden görüntüyü sistemleri üzerine kaydedebilmektedirler.

Bir makalemizin daha sonuna geldik. Bir başka makalede daha görüşmek üzere.

.Net Compact Framework 2.0 – Mobil Cihazlarda Socket Programlama – II

Saturday, January 12, 2008 11:43:39 PM (GTB Standard Time, UTC+02:00)

Makalemizin ilk bölümünde ifade edildiği üzere Mobil Cihazlar üzerinde Socket uygulamaları geliştirebilmeyi telaffuz etmek bundan yaklaşık 3-4 yıl öncesine kadar çok nadir görülebilirdi. Günümüzde ütopik ; en azından çok yüksek programlama bilgisi gerektirebilecek birçok kavramı .Net Framework ; akabinde mobil cihazlar üzerinde .Net Compact Framework ile çok anlaşılır ve basit bir seviyede masaüst ve mobil cihaz uygulama geliştiriciler gerçekleştirebilmektedirler.

Konuya bu açıdan bakıldığında .Net Framework ve .Net Compact Framework’ ün ; özellikle makalemizin asıl konusu gereği mobil cihazlar üzerinde .Net Compact Framework’ ün 2.0 sürümünden itibaren ne kadar başarılı ve güçlü olduğunu makalemizin ilk kısmında birçok noktadan değinerek ifade etmiştik.

Bu makalemizde ise teorik bilgilerin yanısıra ; ilk makalemizde hedeflenen senaryonun ; bir mobil cihaz chat uygulamasının ikinci bölümüne ; mobil cihaz uygulamasını ayrıntılı bir şekilde anlaşılır ekran görüntüleri ile geliştirmeye çalışacağız. Hatırlanabileceği üzere ilk bölümde masaüstü bilgisayarımız üzerinde 15423 numaralı TCP Portu üzerinden “Asenkron Mimari” ile süslenmiş bir sunucu uygulaması geliştirmiştik. Bu noktada ifade etmemiz gerekebilirki geliştirmiş olduğumuz sunucu sadece mobil cihazlar ile çalışacak şekilde tasarlanmamıştır. Standart bir masaüstü socket uygulaması üzerinden bağlantı kurabilecek şekilde ; konuşabilecek şekilde tasarlanmıştır.

Cümlenin son kısmına dikkat edilecek olursa uygulamanın tasarım aşamasında mobil cihazların bağlanabileceği yapıda özelleştirilmiş herhangi bir çabanın sarfedilmediğinden bahsedilmektedir. Bu cümleden de çıkarılabileceği üzere makalemizin ilk bölümünde ifade edildiği şekilde, Socket uygulamaları geliştirilmesi ile ilgili kavramların neredeyse hepsinin masaüstü socket uygulamaları ile birebir aynı olduğu rahatlıkla anlaşılabilir.

Bu noktadan itibaren hiç vakit kaybetmeden ilk bölümde geliştirmiş olduğumuz masaüstü sunucumuz ile haberleşebilecek ve aynı zaman sürecinde mesajlaşabilecek bir Mobil Cihaz Chat uygulaması geliştirelim.

İlk adımda diğer tüm makalelerimizde olduğu üzere standart bir C# Smart Device Application projesi açarak işe başlıyoruz.

Bir sonraki adımda şekilde arayüzü tasarlıyoruz. Amaç girilen ip adres / port kombinasyonu üzerinden geliştirmiş olduğumuz sunucu uygulamasına “dünyanın herhangi bir noktasından” iletişim kurabilecek ve “asenkron mimari üzerinden” mesajlaşabilecek bir mobil cihaz uygulaması geliştirmektir.

Şekilden de anlaşılabileceği üzere form üzerine basit ve temel Mobil Cihaz Windows form kontrolleri yerleştirerek uygulama arayüzünü tasarlamış oluyoruz. Form üzerine “sunucu ile kurulacak olan başarılı bağlantı sonucunda” mesajları girebileceğimiz bir metin kutusu ; mesaj gönderdiğimiz süreçte ekran üzerinde görünecek olan isim bilgimizi girebileceğimiz bir metin kutusu ; sunucu adresi ve port değerini girebileciğimiz bir metin kutusu ; gelen / gönderilen mesajların listeleneceği bir liste kutusu ve son olarak bağlantı kurma ile ilgili eylemi tetikleyecek olan bir buton kontrolü yerleştiriyoruz.

Ve sıra geldi kod blokları üzerinde çalışmaya.

Bu noktada dikkat edilecek unsur Mobil Cihaz üzerinde çalışacak olan uygulamamız adına geliştirecek olduğumuz kodların makalemizin ilk bölümünde geliştirmiş olduğumuz masaüstü sunucu uygulamasını geliştirirken yazdığımız kodlar ile neredeyse birebir aynı olduğudur. Sunucu uygulamasında geliştirildiği üzere bu noktadada gerekli nesnelerin tanımlamaları yapılacak, socket ayarları belirlenecek, ilgili referanslar verildikten sonra uygulamamız sunucu uygulamamız ile haberleşip mesajlaşmaya başlayacaktır. Hiç vakit kaybetmeden uygulama kodlarını geliştirmeye devam edelim. Bir önceki uygulamamızda olduğu gibi ilk noktada uygulama içerisinde kullanacak olduğumuz nesne referanslarını tanımlayalım.

Şekil üzerindende anlaşılabileceği üzere uygulama içerisinde tanımlı olan nesnelerin referanslarını global tanım alanında tanımlamış olduk. Bu noktada DefaultDelege isimli delegenin ayrıntılı işlevinden bir önceki makalede bahsetmiştik.

Sıra geldi asenkron mimari üzerinden çağırılan metotların işlerini tamamladığında gelip haber verecekleri CallBack metotlarını tanımlamaya. Uygulama içerisinde tasarım ve önem bakımından CallBack metotlarının yerinin başka olduğunu yine bir önceki makalemizde ifade etmiştik.

Gelen mesajın işlenmesi, yeni mesajların beklemeye başlatılması v.s. gibi birçok önemli unsur CallBack metotları olarak ifade ettiğimiz bu metotlar içerisinde gerçekleştirilmektedirler.

Ve ilk CallBack metodumuz. Sunucu uygulaması ile bağlantı kurulduğu süreçte yakalanacak olan bu metot içerisinde socket’ imiz asenkron olarak “mesaj bekleme” durumuna geçirilmektedir. Mesaj geldiğinde ise MessageDelegate delegesinin adreslediği metot çalıştırılmaktadır. Hiç vakit kaybetmeden bu delegenin adreslediği CallBack metodunu yazalım.

Bu metot içerisinde ise mesaj geldiğinde içi dolu olan byte[] dizimizin (MessageBuffer) içerisinde barındırdığı mesajı liste kutusu içerisine ekliyoruz. Fakat bu noktada dikkat edilmesi gereken en önemli unsur bu ekleme işleminin worker thread içerisinden değilde primary thread içerisinde gerçekleştirildiğidir. Bu amaca uygun olarak lstMESSAGES isimli liste kutumuzun Invoke metoduna ekleme işleminin gerçekleştirileceği metodun adresini barındıran dlg isimli delegemizi gönderiyoruz.

Son olarak dlg isimli delegenin adreslediği “mesaj ekleme” ile ilgili metodumuzu tanımlıyoruz.

Gerçekleştirilen tek eylem gelen byte[] dizisini türkçe karakter setine uygun olarak metne dönüştürüp liste kutusu içerisine eklemektir.

Sıra geldi uygulamanın yaşam süreci başlatıldığında gerçekleştirilecek olan standart eylemleri tasarlamaya. Sunucu uygulamamız üzerinde hazırladığımız yapının neredeyse birebir aynısını mobil cihazımız üzerinde tasarlıyoruz. Uygulama ekranı açıldığında standart olarak bir socket tanımlanacak, 54123 numaralı port ile bind edilecek ve gerekli istek geldiğinde bağlantı kurulacaktır. Değinilmesi gereken bir önemli nokta daha ise uygulama ekranı açıldığında bir önceki bölümde tanımlanan delegelerin adresleri belirlenecektir. Şekildeki kod bloğu üzerinden devam ediyoruz.

Kod bloğu dikkatli incelendiğinde bir önceki sunucu uygulaması içerisinde tasarlanan yapı ile neredeyse birebir aynı olduğu kolayca farkedilebilmektedir. Ne kadar ilginç...

Bu noktada gerçekleştirilen başka bir yapı ise delegelerin tanımlanması ve gerekli metot adreslerinin belirlenmesidir. Hiç vakit kaybetmeden kaldığımız noktadan devam ediyoruz.

Sırada uygulama ekranı üzerine yerleştirilmiş button kontrollerine tıklandığı zaman gerçekleştirilecek eylemlere. İlk durağımız Connect button’ u.

Connect button’ una tıklatıldığında uygulama ekranı yüklendiğinde tanımlanan socket objesi üzerinden “asenkron mimari” yardımıyla sunucu üzerine bağlantı kurulmak istenmektedir. Bu noktada sunucu adresi “ : “ operatörü üzerinden iki parçaya ayrılmakta ; ilk parça IP Adresini ikinci parça ise port bilgisini ifade etmektedir.

Bağlantı kurulma sürecinde uygulama ekranı üzerinde herhangi bir kilitlenme yaşanmamakta ; Socket.BeginConnect metodu üzerinden dönen IAsyncResult yardımı ile bağlantı kurulup kurulmadığı sürekli kontrol edilmekte ; kurulmadığı süre zarfında Application.DoEvents() metodu üzerinden uygulama ekranı serbest olarak çalıştırılmaktadır.

Başarılı bir bağlantı kurulabildiği taktirde uygulama ekranı üzerinde bulunan kontrollerin erişilebilirliği değişmekte ; mesaj paneli aktif hale gelmektedir.

Şekildeki kod bloğu üzerinden uygulama tasarımına devam ediyoruz.

Sıra geldi mesajı gönderecek olan kod bloğunu tasarlamaya. Gerçekleştirilecek olan tek eylem başarılı bir bağlantı sonucunda aktif hale gelen socket objemiz yardımı ile girilen metin mesajını byte[] dizisine çevirip karşı sunucuya göndermek olacaktır.

İşte bu kadar ! Kod bloklarına dikkat edilecek olursa yapı sunucu uygulaması ile neredeyse birebir aynı olarak ifade edilebilir ! Yaşasın .Net Compact Framework 2.0 ! :)

Hiç vakit kaybetmeden uygulamamızı test ediyoruz. Bu noktada dikkat edilecek unsur senaryo gereği ilk olarak sunucu uygulamamızı çalıştıracak olup ilgili sunucuya “aynı blok değerleri üzerinden” IP Adresi alabilmiş bir fiziksel cihaz ya da mobil cihaz emülatörü yardımıyla bağlantı kuracağız. Sunucu uygulamasını çalıştırıp Sunucuyu başlatıyoruz.

Start Server button’ una tıkladığımızda işletim sistemimiz uygulamamızın bir portu dinlemeye çalıştığını ve bunun engellenip engellenmeyeceğini soracaktır. Unblock seçeneğini seçerek sunucumuzu dinleme moduna geçiriyoruz.

Sıra geldi mobil cihaz uygulamasını sunucuya bağlanabilecek şekilde yapılandırmaya. Örnek olarak çalıştırılan sunucunun IP Adresi 10.5.10.37, port değeri ise 15423’ tür. Bu değerleri kullanarak mobil cihazımız üzerinde gerekli bağlantı işlemlerini gerçekleştiriyoruz.

Connect’ e tıklıyoruz :

Ve bağlantı kuruldu ! Mesajlaşmaya başlıyoruz :

Sonuç mükemmel ! Bir makalemizin daha sonuna geldik. Başka bir makalede daha görüşmek üzere.

.Net Compact Framework 2.0 – Mobil Cihazlarda Socket Programlama - I

Saturday, January 12, 2008 11:43:12 PM (GTB Standard Time, UTC+02:00)

Genel hatlarıyla makalemizin konusunun başlığına bundan yaklaşık 3-4 sene önce bakılsaydı birçok uygulama geliştirici için böyle bir sistemi gerçekleştirmek ütopik ; belkide, imkansız olarak düşünülebilirdi. Mobil Cihazlar’ dan öte standart Windows işletim sistemimiz üzerinde Socket’ ler üzerinden haberleşip birbirleri arasında veri transferi gerçekleştiren uygulamalar geliştirebilemek için bile bundan kısa bir süre öncesine kadar yüksek bir programlama bilgisi gerektirmekte ; herşeyden öte işletim sistemimiz üzerindeki API (Application Programming Interface) Fonksiyonlarını bilmemizi gerektirmekdeydi.

Olaya bu açıdan bakıldığında Socket programlama her zaman uygulama geliştiriciler için bir problem ; en azından bir önceki paragrafta belirtildiği üzere yüksek programlama bilgisi gerektiren bir kavram olmuştur.

2000 yılında .Net Framework “dünyası” ile tanıştığımızda ise neredeyse tüm sıkıntılarımız sona ermiş, yepyeni bir platform ile karşı karşıya kalmıştık. Az önce üzerinde konuştuğumuz yüksek porgramlama bilgisi gerektiren birçok kavramı .Net Framework üzerinde çok daha kolay bir şekilde gerçekleştirmenin verdiği rahatlık ve esneklik ile çok daha büyük ölçekli ve hatasız projeler günümüzde birçok platform üzerinde geliştirilmektedir.

Konuyu bu noktada toparlamak gerekirse birçok noktasında olduğu gibi .Net Framework üzerinde Socket uygulamaları geliştirmekte eskiye nazaran çok daha az efor sarfedilerek gerçekleştirilebilmektedir. System.Net.Sockets NameSpace’ i içerisindeki sınıfları doğru yer ve doğru kombinasyonlar üzerinden kullanarak uygulama geliştiriciler .Net Framework üzerinde çok optimize ve sağlam Socket uygulamaları geliştirebilmektedirler.

Peki .Net Framework üzerindeki bu esnek yapıya .Net Compact Framework üzerinde hangi oranda sahip olabilmekteyiz ? Mobil Cihazlar üzerinde Socket uygulamaları geliştirmek günümüzde hala bir ütopyamıdır ?

İşin biraz derinine inildiğinde özellikle 2.0 sürümü ile birlikte .Net Compact Framework kendisine hayranlık bırakabilecek seviyede başarılı ; konumuz ile ilişkilendirdiğimizde ise hayli sağlam bir grafik çizmektedir.

Socket uygulamaların geliştirilmesi bakımından neredeyse .Net Framework ile başabaş giden .Net Compact Framework , .Net Framework üzerinde olduğu gibi işletim sistemi üzerinde tanımlı olan API Fonksiyonlarını kullanan managed metotları uygulama geliştiricilerin kullanımına sunmaktadır.

Bu makalemizde ise sayfalar dolusu teori ile konuyu anlatmak yerine, Masaüstü Bilgisayarımız üzerinde çalışacak olan bir sunucu uygulaması  ile Mobil Cihaz üzerinde çalışacak olan bir istemci uygulamasını baz alan ; Socket’ ler üzerinden birbirleriyle haberleşen bir mobil chat uygulaması geliştireceğiz.

Bu noktada üzerinde çalışacak olduğumuz kavramlardan bahsetmeden herşeyin “neredeyse .Net Framework ile birebir aynı” olduğunu belirtmek daha doğru olacaktır.

Ayrıca uygulamanın geliştirilme aşamasında standart seviyede Socket kavramlarını biliyor olduğunuzu kabul edeceğiz.

Fakat her ne olursa olsun uygulamamızın parçalarını geliştirmeye başlamadan önce her iki platform üzerinde de ; .Net Framework ve .Net Compact Framework üzerinde de neredeyse birebir aynı çalışma mekanizmasına sahip Socket sınıfını ve metotlarını yüzeysel olarak incelemek bu noktada daha doğru olacaktır.

Sizlerinde bildiği üzere Socket ; bir uygulamanın dış dünya ile iletişim kurabileceği bir kapı olarak kafamızda rahatlıkla canlandırılabilir. Bu noktada kapının bir adresinin ; tipinin ve o kapıdan nelerin geçebileceğinin bilgisinin belirlenmiş olması kapının dış dünya üzerinde çalıştırılabilmesi açısından yeterli parametreler olabilmektedir.

Uygulama geliştiriciler Socket’ ler yardımıyla onlarca protokolün onlarca tipi üzerinden farklı uygulamalar ile haberleşebilir ; veri transferleri gerçekleştirebilirler. Bugün işletim sistemimiz üzerinde kullanıyor olduğumuz birçok “internet” bazlı uygulama işletim sistemimiz üzerinde tanımlı olan WinSock Fonksiyonları üzerinden socket kullanımını gerçekleştirmekte ; bizleri dış dünyaya bağlamaktadırlar.

Olaya bu açıdan bakıldığında Socket programlamanın hiçbir zaman kolay olmadığından ;ileri bir programcılık bilgisi ve araştırma gerektiğinden yazımızın başında bahsetmiştik.

Fakat .Net Framework’ e bakıldığında ise bu işin Managed sınıflar üzerinden ne kadar kolay gerçekleştirilebildiğinden yazımızın başında bahsetmiştik.

.Net Framework içerisinde bulunan System.Net.Sockets NameSpace’ i içerisinde bulunan Socket sınıfı bu noktada gerekli tüm altyapıyı biz Managed uygulama geliştiricilere sunmaktadır. Yapılması gereken tek şey gerekli parametreleri belirledikten sonra bu sınıfın üretilen instance’ ı üzerinden ilgili metotları çağırmak ve veri transferlerini gerçekleştirmek olacaktır.

Şu an ki amacımız bu sınıfı .Net Framework üzerinde kısaca tanıttıktan sonra senaryomuzun ilk parçasını ; masaüstü sunucu uygulamamızı geliştirmek ve hemen akabinde herşeyin ama herşeyin %95 oranında .Net Compact Framework üzerinde de aynı olduğunu ifade ederek makalemizin ilk bölümünü tamamlayacağız.

Socket sınıfı ile ilgili Teorik amaçlı anlatıma geçmeden önce bu noktada örnek uygulamamızın ilk adımını gerçekleştirmeye başlamak daha doğru olacaktır.

Amacımız Mobil Cihaz üzerinden bağlanabileceğimiz ; TCP Protokolü kullanılarak oluşturulmuş bir Windows Masaüstü Sunucu uygulaması geliştirmek olacaktır.

Bu amaca uygun olarak Standart bir C# Windows Application projesi açarak işe başlıyoruz.

Bir sonraki adımda şekildeki Windows Formunu tasarlıyoruz.

Amacımız basit bir arayüz üzerinden “Start Server” button’ u üzerinden dinleme durumuna geçen sunucu uygulaması ile Mobil Cihaz uygulamamızı haberleştirebilmek. Bunun için basit bir kaç kontrolü form üzerine ekliyoruz. Orda noktadaki kontrol bir ListBox kontrolüdür.

Sıra geldi kodlar üzerinde çalışacağımız noktaya. 

İlk olarak belirtmemiz gereken nokta şu olmalıdır ki  uygulamamız asenkron mimari üzerinden geliştirilmelidir. Aksi takdirde bağlantı gerçekleştirilmesi safhasından itibaren her mesaj beklendiği süreçte uygulama ekranı kitli kalacak ; uygulama herhangi bir işe yaramayacaktır.

Bu noktada Socket sınıfı üzerinden hazır gelen bazı asenkron metotları kullanarak bu mimariyi oturtacağız.

Hızlı bir şekilde kaldığımız yerden devam edelim. Kod tarafına geçtiğimizde temel olarak basit birkaç “Callback” metodu ve birkaç delege yardımı ile Socket nesnemizi oluşturup ; sunucu üzerinden “Listen” moduna geçireceğiz. Bundan sonraki adımlarda yapılacak olan tek şey mobil cihaz üzerinden bağlantıyı kurup mesajlaşmaya başlamak olacaktır.

İlk olarak bazı nesne referanslarını global scope alanı içerisinde tanımlıyoruz.

Dikkat edilecek olursa listenin en tepesine System.Net.Sockets NameSpace’ i içerisinde bulunan Socket sınıfının bir referansı tanımlanmış ; bir altına bağlantı kurulduğu noktada karşı istemciyi temsil edecek olan Socket’ in referansı ; onun altına ise Socket sınıfının asenkron metotları çalışmayı tamamladıklarında gidip haber verecekleri metotların adresini barındırabilecek bir signature’ a sahip ; AsyncCallBack delegesinin bir referansı tanımlanmıştır.

En alta ise karşı istemciden mesaj geldiğinde mesajın içerisine yükleneceği 1MB’ lık bir alan teşkil eden bir Byte[] tanımladık.

Kaldığımız yerden devam edelim.

Uygulama tasarımımız asenkron mimari üzerine geliştirileceğinden belirli eylemler “asenkron” olarak gerçekleştirildiğinde işlemlerin sonucu işleyebilmek ve uygulamanın yaşam sürecine devam edebilmesi adına bazı görevleri yerine getirebilmek için iki adet CallBack metodu tanımlıyoruz.

Hiç vakit kaybetmeden şekildeki kod bloğu ile ilgili gerekli açıklamaları ifade edelim.

Kolayca anlaşılabileceği üzere CallBack metotlarının kod sayfası içerisinde yerleştirilebilmesi için tanımlanmış Callback Methods isimli Region içerisine iki adet metot tanımlanmıştır. Bu metotlardan kırmızı kutu ile ifade edilen AcceptedCallBack metodu sunucuya Mobil Cihazımız üzerinden herhangi bir bağlantı başarılı bir şekilde gerçekleştirildiğinde çalıştırılmakta ; Socket objesinin EndAccept isimli Asenkron “sonlandırma” metodu üzerinden karşı socket’ i refere eden socket objesi alınmaktadır. Bir sonraki adımda ise RemoteSocket ismiyle alınan bu socket objesinin Asenkron mimari üzerinden BeginAccept metodu çağırılmakta ; kısaca karşı Mobil Cihaz üzerinden mesajlar “uygulamayı kitlemeden” beklenmeye başlamaktadır.

Bir alttaki, turuncu kutu ile ifade edilen metotta ise BeginReceive ile başlatılan bekleme süreci sonlandığında ; yani Mobil Cihazımız üzerinden bir mesaj geldiğinde çalıştırılacak olan kod blokları geliştirilmiştir.

İlk olarak dikkat edilecek olan satır gelen mesajın nasıl liste kutusu içerisine eklendiğidir.

Bir önceki metotta belirtildiği üzere gelen byte dizisi MessageBuffer isimli byte dizisi içerisinde tutulacaktır. Bu noktada System.Text.Encoding.GetEncoding(1254).Getstring metodu üzerinden faydalanarak gelen byte dizisini “türkçe karakter setine uygun olarak” metne dönüştürüp liste kutusu içerisine ekliyoruz.

Bu satırdan sonra yazdığımız satırda ise MessageBuffer dizisini “yeni gelecek olan” mesajlar için temizliyoruz ; ve uygulamamızı “mesajların gelebilmesi” adına tekrar “mesaj bekleme” moduna geçiriyoruz.

İşte en önemli kısımları halletmiş olduk. Sıra geldi uygulamamızı çalıştıracak olan Socket tanımlama ve mesaj gönderme işlemlerinin gerçekleştirildiği kod bloklarını geliştirmeye.

Amacımız sistemimiz üzerinde 15423 numaralı TCP portu üzerinden dinlemeye ve mesaj göndermeye yarayan bir socket tanımlamak olacaktır. Hiç vakit kaybetmeden şekilde kod bloklarını geliştiriyoruz.

Kod bloğunu ayrıntılı olarak incelediğimizde uygulamamız açıldığında sistem üzerinde TCP protokolü 15423 numaralı porttan dinleyecek ve Stream ; yani akış işlemlerinin gerçekleştirilebileceği bir Socket objesi tanımlanmaktadır. Bir sonraki satırda ise bu socket objesi sistemimiz üzerindeki fiziksel bir port ile ilişkilendirilmektetir. Ayrıca uygulama ekranı yüklendiğinde delegemizin objesi tanımlanmakta ; son olarak ise Asenkron işlemlerde daha önceki makalelerimizde bahsettiğimiz “bir objeye o’ nun oluşturulduğu thread dışında farklı bir thread üzerinden erişmeye çalıştığımızda yaşanan CrossThreadOperationException hatasına karşı” Control.CheckForIllegalCrossThreadCalls static değişkenine “sorun çıkarmaması adına” false değerini veriyoruz.

Button1 isimli Start Server button’ una bastığımızda ise tanımlanan socket objemizi Listen metodumuz üzerinden dinleme moduna geçiriyoruz. Ve BeginAccept metodu üzerinden asenkron mimariyi kullanarak uzaktan gelecek olan bağlantıları kabul edebilecek şekilde yapılandırıyoruz.

Son olarak btnSEND isimli button’ umuza tıkladığımızda ise yazılan metin System.Text.Encoding.GetEncoding(1254).GetBytes metodu üzerinden byte dizisine çevirmekte ve “eğer bağlı bir socket var ise” yani RemoteSocket referansı “null” değil ise karşı noktaya yani mobil cihazımıza göndermektedir.

İşte bu kadar !

Makalemizin ilk bölümünün sonuna geldik. Bir sonraki makalemizde bu makalede geliştirdiğimiz sunucu ile haberleşecek bir mobil cihaz uygulaması geliştireceğiz.

.Net Compact Framework 2.0 – Mobil Cihazlarda Web - Windows Vista Web Service Deployment

Saturday, January 12, 2008 11:42:26 PM (GTB Standard Time, UTC+02:00)

Dağıtık uygulama senaryolarına baktığımızda muhtemelen karşılaşabileceğimiz en büyük problem ortam içerisindeki cihazların birbirleriyle haberleşme esnasında kullanacakları platformdur. Kullanılacak olan altyapının maliyeti yükseltmesi ; ticari bir ortamda pekte hoş karşılanmayacaktır. Bu noktada esnek, geliştirilebilir, güvenli ve “maliyeti düşük” bir platforma ihtiyaç duyulmaktadır.

Olaya bu perspektif üzerinden baktığımızda XML Web Servislerinin bu ihtiyacı fazlasıyla karşıladığını ; dağıtık uygulama senaryolarında “lokasyon’ dan bağımsız” sistemleri birbirlerine maliyeti yükseltmeden bağlayabildiğini rahatlıkla söyleyebiliriz. Belirli güvenlik seçenekleri çerçevesinde XML Web Servisleri yeni jenerasyon uygulama geliştiricilerin dağıtık uygulama senaryolarında tercih olarak seçebilecekleri başarılı seçeneklerin başında gelmektedir.

Bu makalemizde ise dağıtık uygulama senaryolarında en sık karşılaşılabilecek bir senaryoyu ; Mobil Cihazlar üzerinde XML Web Servislerinin kullanımına değineceğiz.

Bu noktada konunun daha rahat anlaşılabilmesi açısından makalenin devamında örnek bir uygulama geliştirilecektir.

Hiç vakit kaybetmeden makalemizin ilk bölümünde Mobil Cihazlar üzerinden çağırılabilecek bir Xml Web Servisi geliştirelim. İkinci aşamada ise bu Web Servisi ile Mobil Cihaz uygulamamız arasındaki bağlantıları gerçekleştirip makalemizi bitireceğiz.

Web Servisimiz girişi yapılan ürün numarası üzerinden kullanıcının Mobil Cihaz üzerindeki uygulamasına gerekli ürün bilgilerini gönderecektir. Bu noktada uygulama güvenliği kullanıcıdan alınan Müşteri kodu olacaktır.

Uygulamamıza başlamadan önce örneğimizde kullanacak olduğumuz veritabanının Northwind veritabanı olduğunu bu noktada belirtmek doğru olacaktır.

Hiç vakit kaybetmeden XML Web Servisimizi geliştirmeye başlayalım. XML Web servisimiz içerisinde iki adet metot olacaktır. Metotlardan ilki kullanıcıdan Müşteri Kod bilgisini isteyecek ve eğer bu bilgiyi Customers tablosu üzerinden doğrulayabilirse uygulamanın ikinci ; Ana ekranını ekrana getirecektir. Bir diğer metot ise Kullanıcı bilgilerinin doğrulanmasından sonra Kullanıcıdan ürün numarasını isteyecek ; sorgulama sonucunda ise eğer bilgi doğrulanabilirse ilgili ürün bilgisini ekrana getirecektir.

İlk olarak Yeni bir Asp.NET Web Servis projesi oluşturarak işe başlayalım.

Proje başarıyla oluşturulduğunda ilk adımda Müşteri Kod bilgisini kontrol eden metodu yazarak örneğimize devam edelim.

Metodu ayrıntılı bir şekilde incelediğimizde yapının çokta karmaşık olmadığını rahatlıkla anlayabiliriz. Metot kullanıcıdan string tipinde Müşteri Kod bilgisini istemekte ve bu bilgiyi doğrulaması sonucunda kullanıcıya sonuç ile ilgili bool tipinde bir değer döndürmektedir. Metodumuzu Internet Tarayıcımız üzerinden denediğimizde ;

Müşteri adı olarak “ALFKI” değerini giriyoruz ve metodumuzu tarayıcımız üzerinden Invoke ediyoruz.

Ve sonuç ! Metodumuz başarılı bir şekilde müşteri kod bilgisini veritabanı üzerinden sorgulayabilmektedir. Sıra geldi ikinci metodumuza. Bu noktada kullanıcımız başarılı bir şekilde giriş yapabilmiş ise ürün numarasını ikinci metodumuza parametre değeri olarak gönderecek ; ürün numarası tablo içerisinde bulunabilmiş ise ilgili ürünün bilgileri kullanıcıya ArrayList içerisinde döndürülecektir.

Metodu ayrıntılı bir şekilde incelediğimizde DataReader üzerinden dönen tek bir satır olduğunu ; bu satırı satırın içerisindeki kolon sayısı kadar dönen bir döngü içerisinde okuduğumuzu rahatlıkla anlayabiliriz. Satır içerisindeki her bir kolon “Kolon Adı : Kolon Değeri” şeklinde ArrayList içerisine eleman olarak eklenmektedir.

Uygulamanın ikinci metodunu tarayıcımız üzerinde test ettiğimizde :

Metodu çalıştırmak istediğimizde :

1 değerini metin kutusu içerisine giriyoruz ve Invoke button’ una tıklıyoruz.

Ve sonuc ! Mükemmel ! Sıra geldi mobil uygulamamıza. Mobil uygulamamız içerisinde iki adet form bulunacaktır. Formlardan ilki kullanıcıyı karşılayacak ; Müşteri kod bilgisini kullanıcıdan isteyecektir. Kullanıcının bu bilgisi Web Servisi üzerinden doğrulandığında uygulamamızın ikinci formu ekrana gelecek ve gerekli bilgiler kullanıcıdan istecenecektir. Bu noktada Mobil Cihaz uygulamamızı geliştirmeye geçmeden önce Web Servisimizi Lokal Web sunuzumuz üzerinden Publish etmemiz gerekmektedir. Bu şekilde Web Servisimiz Lokal Makinemiz üzerinden dış dünyaya sunulmuş olacaktır.Projemizin üzerine sağ tıklıyoruz ve Publish Web Site seçeneğini seçiyoruz.

Gerekli değerleri belirleyip OK’ e tıklıyoruz.

Tek yapmamız gereken uygulamamızın bulunduğu klasörü Internet Information Services üzerinde bir Application Folder (Uygulama Klasörü) olarak tanımlamış olmak.

Seçeğe tıkladığımızda ise :

OK’ e tıklayarak uygulamamızı IIS üzerinde tanımlamış oluyoruz.

Artık web servisimize http://MakinemizinAdi/UygulamaAdi/Service.asmx adresi üzerinden erişilebilmektedir.

Vakit kaybetmeden makalemizin ikinci bölümüne devam edelim. İlk olarak işe yeni bir C# - Smart Device – Device Application uygulaması açarak başlıyoruz.

Bir sonraki adımda ise proje içerisinde standart olarak gelen Windows Form’una ek olarak yeni bir Windows Form ekliyoruz. Form’ un isim değerine frmMAIN değerini atıyoruz.

Ve uygulamamızı geliştirmeye başlıyoruz. İlk form yani frmLOGIN içerisinde şekildeki tasarımı gerçekleştiriyoruz.

Web Servisi entegrasyonu kısmına geçmeden önce ikinci yani Ana Formumuzu’ da geliştirelim.

Ve sonuç ! Form üzerine bir metin kutusu, bir button ve bir Liste kutusu ekledikten sonra sıra geldi Web Servis entegrasyonuna. Bu noktada olayın ne kadar kolay olduğunu ifade edebilmek amacıyla sadece şunu söylemek yeterli olacaktır ; .NET Framework üzerinde bu iş nasıl gerçekleştiriliyorsa .NET Compact Framework üzerinde de o şekilde ! Projenin References sekmesi üzerine sağ tıklanıp Add Web Reference seçeneği üzerinden uygulama geliştiriciler Mobil Cihaz projeleri üzerinde Web Servislerini kullanabilirler.

Add Web Reference seçeneği üzerinden Web Servisimizi Mobil Cihaz uygulamamız ile ilişkilendiriyoruz.

Ve Web Servisimizin lokasyonumuzu yazıyoruz. Bu noktada dikkat etmemiz gereken yapı Web Servisimizin Lokaldeki makinamız üzerinde bulunmasından ötürü adresi “localhost” şeklinde belirtmiş olabiliriz. Bu adres modeli Mobil Cihaz üzerinde bulunamayacak ; haliyle Web Servisimiz ile Mobil Cihazımız haberleşemeyecektir. Doğru adres değeri ise Web Servisinin bulunduğu makinenin ismini ; yani makinemizin ismini yada IP adresimizi değer olarak belirleyerek soruna çözüm bulmuş olabiliriz.

Ne kadar basit değilmi ? Standart .NET Framework masaüstü uygulamalarında olduğu gibi tek yapmamız gereken Web Servisimize erişebilecek “Proxy” sınıfının otomatik olarak oluşturulabilmesi için “Add Reference” button’ una tıklamak olacaktır.

Web Reference Name değerine NorthwindWS değerini belirleyip “Add Reference” seçeneğine tıklıyoruz.

Ve sonuç ! Sıra geldi uygulamamızın giriş ekranı üzerindeki kod bloğunu hazırlamaya. Tek yapmamız gereken uygulama açıldığında Servis Proxy sınıfımızın bir kopyasını almak ve Kullanıcı bilgilerini kontrol eden metodu bu kopya üzerinden çalıştırmak olacaktır.

Kodları şekildeki gibi belirledikten sonra uygulamamızı Fiziksel Cihaz / Emülatör üzerinde çalıştırıyoruz.

Değer olarak ilk adımda yanlış bir Müşteri Kod bilgisi giriyoruz. İkinci adımda ise doğru bir değer girdikten sonra ana ekran görünümünün ekrana geldiğini görmemiz gerekmektedir.

Doğru bir Müşteri Kod bilgisi girdiğimizde ise :

Uygulamanın ana ekranı ekrana gelmektedir. Tek yapmamız gereken ana ekran üzerinde çalışacak olan kodları yazmaktır. Gerçekleştirilecek tek eylem girilen ürün numarası bilgisini Web Servisimiz üzerindeki ilgili metoda göndermek ve gelen object[] içerisindeki metinleri liste kutusu içerisine eklemektir.

Uygulamayı Fiziksel Cihaz / Emülatör üzerinde çalıştırdığımız ve Müşteri Kod bilgisi ekranını başarılı bir şekilde geçtikten sonra :

Ve sonuç !

Ürün numarası Web Servisi üzerinden veritabanımızda sorgulanıp gerekli ürün bilgisi ekrana getirilmiştir !

Bu makalemizde örnek bir Web Servisi uygulamasının Mobil Cihazlar üzerinde kullanımına değindik, başka bir makalede daha görüşmek üzere.

.NET Compact Framework 2.0 – Mobil Cihazlarda Application.DoEvents() Kullanımı

Saturday, January 12, 2008 11:41:51 PM (GTB Standard Time, UTC+02:00)

Masaüstü ya da Mobil Cihaz Form uygulamalarında yaşanan en büyük problemlerden birisi döngülerin çalıştırıldığı süreç esnasında uygulama ekranı üzerinde yaşanan kilitlenmelerdir. Bu konuyla ilgili daha önce http://www.yazgelistir.com/Makaleler/1000001208.ygpx adresinde Asenkron Mimarinin uygulanması ; başka bir deyişle işlemlerin farklı bir thread içerisinden yürütülerek halledilebileceğinden bahsetmiştik. Bu makalemizde ise işlemlerin çalıştırılma süreci içerisinde yaşanan bu beklemelerin temel sebebinden bahsedip ; buna farklı bir perspektiften ; Application.DoEvents() metodu üzerinden çözüm arayacağız.

Asıl konumuza geçmeden önce işletim sistemimiz üzerinde bir uygulama başladığı andan itibaren yaşanan süreçten bahsedelim. Bilindiği üzere Windows CE ya da herhangi bir Windows tabanlı işletim sistemi üzerinde herhangi bir kaynak üzerinde gerçekleşen bir olay ile ilgili işletim sisteminin gösterdiği tepkilere bildiğimiz “Olay (Event)” ismi yerine “Mesaj (Message)” ismi verilmektedir. Bu noktada işletim sistemi üzerinde gerçekleştirilen herhangi bir eylem uygulama geliştiriciye Mesaj olarak gönderilmektedir. Zaten Buton üzerinde tıkladığımızda ilgili buton’ un tıklatıldığını işletim sistemimiz donanımsal seviyeden yakalayıp .Net Framework’ e iletmekte ; Olay (Event) olarak tanımladığımız tetikleyiciler uygulamalarımızda fırlatılmaktadır.

Üzerinde konuştuğumuz bu süreç ana uygulama herhangi bir sebepten kapatılmadığı ya da sonlandırılmadığı süre boyunca istisnasız devam etmekte ; gerçekleştirdiğimiz her eylemin karşılığında işletim sistemimiz üzerinden mesajlar fırlatılmakta ve bu mesajlar .Net Framework tarafından yakalanıp işletilmektedir.

Konuyu biraz daha ayrıntılı incelediğimizde istisnasız devam eden bu süreç içerisinde incelenmesi gereken –ki sorunun temel kaynağı olarak ifade edilebilecek- önemli bir başlık daha bulunmaktadır.

Bir önceki örneğimizde uygulama ekranımız üzerine yerleştirilen standart bir button’ un üzerinde gerçekleştirilebilecek en standart eylemden ; üzerine tıklamaktan bahsettik. Bu noktada mantık çerçevesinde düşünüldüğünde ekran üzerinde aynı anda iki butona tıklayamayacığımız açık ve net bir sonuçtur.

Olaya bu açıdan baktığımızda standart yaklaşımla gerçekleştirdiğimiz eylemlere karşılık olarak gönderilen mesajlar işletim sistemimiz üzerinde belirli bir sırayla gönderilip işletilmektedir. Özel, spesifik bir durum dışında bir eylem sonucunda belirli bir iş gerçekleştirildiğinde işletim sistemi üzerinden gönderilen diğer mesajlar uygulama tarafında bekletilmekte ; bir önceki mesajın sonucu başlatılan iş tamamlanana kadar işletilmemektedirler. Peki bu noktada yaşanan nasıl bir problem olabilir ; biraz bu konuya değinelim.

Örnek bir senaryo olarak makalemizin başında adresi verilen Asenkron Mimari ile ilgili makalemizde gerçekleştirilen bir senaryoyu ele alalım. Uygulama içerisinde belirli iki sayı arasında ; ya da belirli bir koşul gerçeklendiği zaman sürecinde onlarca belki yüzlerce kez çalışması gereken bir döngünün olduğunu düşünelim. Bu döngünün döndürüldüğü ; başka bir deyişle çalıştırıldığı süreç içerisinde ise görsel anlamda bazı görevleri yerine getirelim-ki örnek vermek gerekirse gelen her sayıyı bir liste kutusu içerisine eklemek olabilir.

Bir önceki paragrafta anlatıldığı üzere bu “iş” gerçeklenirken işletim sistemi üzerinden onlarca ; belki yüzlerce mesaj fırlatılmakta, fakat o süreç boyunca sistem “döngü” ‘ ye odaklandığı ve onunla ilgili mesajları işlediği için diğer mesajları kuyrukta bekletmektedirler.

Peki az önce üzerinde konuştuğumuz üzere ; özel & spesifik bir durumdan bahsediyorsak ; yani döngü dönerken liste kutusu içerisine eklenen rakamları canlı olarak görmek istiyorsak ; daha açık anlatmak gerekirse gelen rakamların liste kutusuna eklenmesi ile ilgili işletim sistemi üzerinden gelen mesajların döngü çalışırken işletilmesi için nasıl bir yapıyı uygulamamız gerekmektedir ?

İşte bu noktada makalemizin başlığını oluşturan bir metot ; Application sınıfı içerisinde bulunan DoEvents() metodu karşımıza çıkmaktadır.

Application.Run() metodu ile yaşam sürecine başlayan Windows Form uygulamamız içerisinde kuyrukta bekletilen mesajların işlenmesi ile ilgili bir metot olan DoEvents() metodu makalemizinde konusunda ifade edildiği üzere bu tip bekletme durumlarında hayat kurtarmaktadır. Özellikle döngü, koşul bazlı süreçler ele alındığında kullanıcılar kuyrukta bekletilen mesajları işleterek sistemin “olması gerektiği gibi” çalışmasını sağlayabilmektedirler.

Bu noktada konunun daha rahat anlaşılabilmesi açısından örnek bir uygulama geliştirmek çok doğru olacaktır. Senaryomuza göre bir while döngüsü içerisinde koşul sağlandığı sürece o an aktif sayaç değeri liste kutusuna eklenecek ; bu ekleme işinin görsel sonucu canlı olarak ekranda gösterilecektir.

Bunun için ilk olarak bir Smart Device C# uygulaması açıyoruz.

Bir sonraki adımda form üzerine bir buton ve bir liste kutusu kontrolü yerleştiriyoruz.

Ve şekildeki kodları yazarak uygulamamıza devam ediyoruz :

Kodu incelediğimizde basit bir while döngüsünün hazırlandığını rahatlıkla farkedebiliriz. Gerçekleştirdiğimiz tek eylem ise Button’ a tıkladığımızda koşulun sağlanıp sağlanmadığını kontrol etmek ; koşul sağlandığı süre içerisinde de Sayac değerini liste kutusu içerisine eklemek olacaktır. Bu şekilde uygulamamızı çalıştırdığımızda ise :

Scrollbar’ ın küçüldüğünü ; yani sayıların eklenmesi ile ilgili mesajların geldiğini fakat bunların görsel anlamda işletilemediğini rahatlıkla görebiliriz. Bu noktada yaşanan problem ile ilgili yazının başında ayrıntılı bir açıklamada bulunmuştuk. Yapmamız gereken tek şey bekletilen mesajların kuyruktan çekilmesi ve işletilmesi olacaktır ; ki bu noktada Application.DoEvents() metodu karşımıza çıkmaktadır.

Application.DoEvents() metodu her çağırıldığında kuyrukta bekletilen mesajlar otomatik olarak işlem görmektedir. Bu noktada döngü her döndüğünde bu mesaj sayısı yükselmekte ; haliyle kimi zaman tıkanmalara sebep olabilmektedir. Bizim bu noktada yapabileceğimiz tek şey döngü her döndüğünde Application.DoEvents() metodunu çağırmak ve anlık olarak sırada bekletilen mesajı ; yani sayının liste kutusuna eklenmesi ile ilgili işlemi gerçekleştirmemiz olacaktır. Kodu şekildeki gibi tekrar düzenleyip çalıştırıyoruz :

Uygulamayı çalıştırdığımızda ise :

Ve sonuç mükemmel ! İşlem devam ediyor olmasına karşın sayılar ekran üzerinde başarıyla görüntülenmektedir.

Bu makalemizde Application.DoEvents() metodu ile kuyrukta bekletilen işletim sistemi mesajlarını kuyruktan çekmeyi mercek altına aldık. Başka bir makalede daha görüşmek üzere.

System.Data.SqlServerCe – Her Yönüyle SqlCeEngine

Saturday, January 12, 2008 11:41:20 PM (GTB Standard Time, UTC+02:00)

Sql Server 2005 Compact Edition uygulama geliştiricilerin beğenisine sunulduğunda birçok yenilikle sahneye çıkmıştı. Bunlardan en önemlisi Sql Server 2005 Compact Edition artık Mobil Cihaz’ lardan sonra Masaüstü uygulamalarında da kullanılabilecekti.

Performans, optimizasyon, birlikte çalışılabilirlik gibi özelliklerini incelediğimizde Basit ve Lokal Veri Depolama senaryolarında Sql Server 2005 Compact Edition çok doğru bir seçenek olacaktır. Bu noktada geliştirilen uygulamaların Sql Server 2005 Compact Edition (bu noktadan sonra Sql CE olarak anılacaktır)veri depolama altyapısı üzerinden programlanabilmesi için managed kod uygulama geliştiriciler sistemlerine Sql CE yükleme paketini kurmaları gerekmektedir. Bu kurulum ile birlikte sistemimize managed Windows Masaüstü ve Mobil Cihaz uygulamalarında kullanabileceğimiz System.Data.SqlServerCe ismi ile kullanabileceğimiz bir referans yüklenmektedir.

Bu referans üzerinden uygulama geliştiriciler tam Sql Server 2005 Compact Edition entegre çalışan uygulama geliştirebilir ; üzerinde aktif olarak çalışıyor oldukları veritabanı üzerinde veri bazlı ve yönetimsel seviyede işlemler gerçekleştirilebilirler. Bu makalemizde bu referans üzerinden uygulama geliştiricilerin kullanımına sunulan ; Sql Server 2005 Compact Edition uygulama geliştirme senaryolarında en temel sınıf olarak kabul edilen bir sınıfı ; SqlCeEngine sınıfını mercek altına alacağız.

SqlCeEngine sınıfı temel anlamda adından da anlaşılabileceği üzere bir Sql Server 2005 Compact Edition motorunu ifade etmektedir. Buradaki motor kelimesinden çıkarmamız gereken anlam temel yönetimsel işlemler gerçekleştirebilecek bir sınıf olarak ifade edilebilir. Genel hatlarıyla sınıfın elemanlarına bakacak olursak ;

listenin çokta karmaşık olmadığını rahatlıkla farkedebiliriz. Metotların ne işe yaradığını teorik olarak anlatmaktansa mobil bir cihaz üzerinde geliştireceğimiz küçük bir örnek bu noktada daha yararlı olacaktır. Örnek .NET Compact Framework 2.0 yüklü Windows Mobile 5.0 işletim sistemine sahip bir Pocket PC cihazı hedef alınarak geliştirilecektir. Bunun için sisteminizde Windows Mobile 5.0 SDK’ nın kurulu olması gerekmektedir.

İlk olarak işe yeni bir Mobil Windows Projesi açarak başlıyoruz.

Bir sonraki adımda makalemizin temel konusu olan sınıfımızın bulunduğu referansı ; System.Data.SqlServerCe referansınızı projemize referans olarak ekliyoruz.

Referansı projemize ekledikten bir sonraki adımda uygulamamızı geliştirmeye hızlı bir şekilde devam edelim. Bu noktadaki amacımız yukarıda ifade ettiğimiz üzere bu referans içerisinde bulunan SqlCeEngine sınıfının metotlarını ve temel amacını mercek altına almak olacaktır.

Hızlı bir şekilde örneğimize devam edelim. Genel hatlarıyla sınıfımızı incelediğimizde yapının nasıl çalıştığını Constructer’ ı üzerinden rahatlıkla anlayabiliriz. Sınıfın Instance’ ını almak istediğimiz zaman karşımıza 2 farklı overloaded constructer çıkmaktadır.

Bunlardan ilki kullanıcıdan herhangi bir parametre istemez iken ikincisi kullanıcıdan mobil cihazınız üzerinde fiziksel olarak bulunan ya da bulunacak olan veritabanına bağlantı kurulacağı noktada kullanılacak olan bir bağlantı cümleciği istemektedir. Bağlantı cümleciği içerisinde kullanabileceğimiz tüm parametrelerin listesini http://msdn2.microsoft.com/en-us/library/system.data.sqlserverce.sqlceconnection.connectionstring.aspx adresinden ayrıntılı bir şekilde inceleyebilirsiniz. Örneğimiz üzerinde Mobil Cihazımızın kök klasörü içerisinde bulunan Yazilim.sdf isimli veritabanına bağlantı kuracağız. Bu noktada bu veritabanının fiziksel olarak olmadığını ; sınıfımız içerisinde belirttiğimiz bağlantı cümleciği yardımı ile oluşturulacağını birlikte uygulayacağız. Yapıcı metot içerisine Bağlantı Cümlesi parametresini şekildeki gibi göndererek bir SqlCeEngine objesi oluşturuyoruz.

Şekilde görüldüğü üzere herhangi bir Kullanıcı Adı / Şifre kombinasyonu belirtilmemiştir ki bu noktada veritabanımızın güvenliği çokta yüksek değildir.

Mantık çerçevesinde baktığımızda bu sınıfı kullanarak gerçekleştireceğimiz yönetimsel işlemleri gerçekleştirebilmemiz için ilk aşamada veritabanımızın fiziksel olarak oluşturulmuş olması gerekmektedir. Bu noktada ilk olarak SqlCeEngine sınıfı içerisinde karşımıza çıkan CreateDatabase() metodu üzerinde örneğimizi uygulamaya devam edelim.

Metot adından da anlaşılabileceği üzere SqlCeEngine objesi içerisinde belirtilmiş olan bağlantı cümleciği içerisindeki patikadaki veritabanını fiziksel olarak oluşturmaya yaramaktadır. Uygulamamızı hiç vakit kaybetmeden çalıştırıyoruz :

Uygulama ekranı açıldığında boş bir form görüyor olmamız gerekmektedir. Fakat uygulamamızı kapatıp mobil cihaz üzerinde belirtilen patika içerisine baktığımızda :

veritabanı dosyamızın başarılı bir şekilde oluşturulduğunu rahatlıkla görebiliriz. Veritabanımıza mobil cihazımız üzerine yüklenen Query Analyzer uygulaması üzerinden bağlantı kurup basit bir tablo ve birkaç satır bilgi ekliyoruz.

Yeni bir tablo ve birkaç satır bilgi ekliyoruz.

Ve bilgiler ;

Run butonuna tıkladığımıza ekran 1 satırın eklendiğine dair mesaj görüntülenecektir. Bu noktadaki amacımız minimal düzeyde bile olsa veritabanımızın içerisinde bilgilerin bulunuyor olmasıdır.

Hızlı bir şekilde sınıfımızın içerisinde bulunan metotları incelemeye devam edelim. SqlCeEngine sınıfı içerisinde herhangi bir t zamanında veritabanının fiziksel dosyasının tutarlılığını inceleyebilmek amacı üzerine kullanabileceğimiz faydalı bir metot bulunmaktadır. Bu metot üzerinden veritabanı içerisindeki “sayfa” ların tutarlılığını belirleyebilir, bir sonraki başlık içerisinde inceleyeceğimiz Repair metodunun gereksinimini belirleyebilirsiniz. Şekildeki kod bloğu üzerinden makalemize devam ediyoruz.

Verify metodunu çalıştırarak fiziksel veritabanı dosyası içerisindeki tutarlığı denetliyoruz. Tutarsız bir durum ile karşı karşıya kalındığında ise Verify metodu uygulama geliştiriciye false değerini döndürmekte ve Repair metodunu kullanmasını gerektiğini söylemektedir. Uygulamayı çalıştırıyoruz :

Veritabanımızın fiziksel anlamda herhangi bir tutarsızlık sorununun olmadığını rahatlıkla anlayabiliriz. Peki ya bu metot sonucunda false boolean değerini elde etmiş olsaydık problemin önüne nasıl geçebilecektik ? Problemin çözümüne geçmeden önce değerin false gelmesinin sebepleri üzerinde kısaca değinmek daha faydalı olacaktır.

Konuyu kısaca ifade etmek gerekirse Verify metodunun false değerini kullanıcıya döndürmesi veritabanının fiziksel dosyası içerisinde hesaplanan Checksum değerlerinin tutarsız olduğunu ; haliyle veritabanı içerisindeki Datapage’ lerin herhangi bir tanesinde bir problem olabileceği anlamına gelmektedir. Sistemin bu şekilde çalışması riskini göze almayacak isek çözüme ulaşmamız için tek bir yöntem bulunmaktadır ; Repair() .

Repair metodu SqlCeEngine sınıfı içerisinde uygulama geliştiricilerin kullanımına gelen ; bu tip tutarsızlık senaryolarında fiziksel veritabanı dosyasını eski haline dönüştürmeye yarayan hayat kurtarıcı bir metot olarak kullanılmaktadır. Senaryomuzda hata olmamasına rağmen Repair metodunun kullanımını kısa bir örnekle açıklamak bu noktada daha doğru olacaktır.

Şekilden anlaşılacağı üzere Repair metodu kullanıcıdan iki adet parametre istemektedir. Bunlardan ilki ConnectionString. ConnectionString parametresinin istenmesinin sebebi “tamir edilmiş” veritabanının bozuk veritabanı dosyasından farklı bir lokasyonda olmasını isteyen uygulama geliştiriciler için metoda parametre olarak eklenmiştir. Eğer “tamir edilmiş” veritabanının aynı lokasyonda ; yani varolan veritabanının üzerine yazılmasını istiyorsak bu parametreye null değer vermek yeterli olacaktır. Bu noktada bir sonraki parametre değerine bakacak olursak RepairOption adını verdiğimiz bir enum değeri kullanıcıdan istenmektedir. Bu enum değerinin istenmesinin amacı ise “tamir edilme” işlemi esnasında bulunan bozuk bölgelere nasıl bir işlem gerçekleştirileceğidir.

Bu enum listesindeki değerler şekildeki gibi oluşturulmuştur ;

Enum listesi içerisinde bulunan değerleri bu noktada kısaca açıklamak faydalı olacaktır.

DeleteCorruptedRows enum değerini belirleyerek Repair() metodu çalıştırıldığında SqlCeEngine objesi “bozuk” veritabanı dosyası içerisinde bulduğu “sorunlu” DataPage’ leri düzeltmeye çalışmadan silecektir. Bir diğer seçenek olan RecoverCorruptedRows seçeneği ise ilk seçeneğin aksine bozuk bulduğu DataPage’ leri düzeltmeye çalışarak eski haline getirecektir. Biz ikinci seçeği seçecek şekilde metodumuzu çalıştırıyoruz.

Bu metot çalıştırıldığında dosyanın fiziksel olarak bulunduğu noktada aynı isimle “tamir edilmiş” versiyonu otomatik olarak oluşturulacaktır.

Makalemize ; SqlCeEngine sınıfının diğer metotlarını inceleyerek devam edelim. Şu ana kadar üzerinde çalıştığımız metotların neredeyse hepsi standart olarak “olmazsa olmaz” metotlar olarak ifade edilebilir. Sırada yine olmazsa olmaz olarak ifade edebileceğimiz ; masaüstü uygulamalarında Sql Server’ ın normal sürümlerini kullanan uygulama geliştiricilerin yakından tanıdığı bir kavramı yerine getiren bir metot ile devam edelim ; Shrink(). Shrink kavramı standart Sql Server sürümleri üzerinde “veritabanının kullanılmayan alanlarını makaslayarak yerden tasarruf” olarak ifade edilebilecek sık gerçekleştirilen bir eylemdir. Bellek miktarı açısından yetersiz olan Mobil Cihazlar üzerinde kullanılmasının ise bu noktada çok doğru olduğu açıktır. SqlCeEngine sınıfı içerisinde bulunan Shrink metodu üzerinden uygulama geliştiriciler veritabanının kullanılmayan alanlarını makaslatarak yerden tasarruf sağlayabilirler. Şekildeki kod satırını ekleyerek uygulamamıza devam ediyoruz :

Sırada SqlCeEngine sınıfı içerisinde “önemli” olarak incelenebilecek son bir metot daha var ; Compact(). Compact metodu yapısı gereği fiziksel veritabanı dosyamızın “adresi “ verilen noktada verilen “yeni” özellikleriyle “gereksiz boşlukları temizledikten sonra” tekrar oluşturulmasını sağlamaktadır. Bu noktada cümle içerisinde geçen “yeni özellikler” kavramını biraz açmak daha doğru olacaktır.

Birçok zaman fiziksel veritabanı dosyamızı (*.sdf) Şifre gibi bazı özellikleri belirlemeyerek oluşturmuş olabiliriz. Bu durum, bundan sonraki kullanımlarımızda veritabanımızın bu şekilde kullanılacağı anlamına gelmemektedir.

Konu ile nasıl bir ilişki var diye araştırdığımızda Compact metodu içerisine aldığı ConnectionString parametresi ile aslında bir nevi “veritabanımızın tüm özellikleriyle” yeni halini oluşturmaktadır. Daha ayrıntılı açıklamak gerekirse Compact metodunun ilk parametresinde verdiğimiz ConnectionString değeri içerisinde Şifre bilgisi bulunıyor ise, veritabanımızın yeni hali bu özelliğe sahip bir şekilde oluşturulacaktır.

Kodu şekildeki gibi çalıştırdığımızda Kök Klasör içerisinde YazilimYeni.sdf ismiyle, sadece“eknozcckcLr” şifresi kullanılarak bağlantı kurulabilecek bir veritabanı oluşturulmuş olacaktır.

Şifre bilgisini belirtmeden bu veritabanına bağlantı kurmaya çalıştığımızda ise :

Çağırılan ilk metot üzerinden şekildeki hatayı alacağız.

Bu makalemizde SqlCeEngine sınıfına ayrıntılı bir şekilde değindik. Bir sonraki makalede görüşmek üzere.

.Net Compact Framework 2.0 – Mobil Cihazlarda XML Serialization

Saturday, January 12, 2008 11:39:15 PM (GTB Standard Time, UTC+02:00)

Serialization kavramı bilindiği üzere nesnenin herhangi bir t zamanında belirtilen “formatter” kullanılarak bellek üzerinde depolanması ve yine herhangi bir t zamanında bellek üzerinde depolandığı yerden “serialize” edildiği zaman sürecindeki değerleriyle tekrardan oluşturulma işlemidir.

Olaya bu açıdan bakıldığında serialization işleminin .Net Framework üzerinde yüzlerce parametresi bulunmaktadır. XML, SOAP ve Binary Serialization olarak 3 farklı format üzerinde incelenebilecek olan bu kavram her birinde farklı avantajlar & dezavantajlar getirmektedir.

Temel hatlarıyla avantajları ve dezavantajlarına baktığımıza göze çarpan en büyük fark XML Serialization’ ın Shallow (Sığ) Serialization, SOAP ve Binary Serialization’ ın ise Deep (Derin) Serialization yapabiliyor olmasıdır. Shallow Serialization’ da Public Member’ lar serialize edilirken , Private Member’ lar serialize edilmemektedir. Deep Serialization’ da ise tüm Member’ lar serialize edilebilmektedir.

Bütün bunların yanında .Net Compact Framework’ e baktığımızda .Net Framework ile kıyaslandığında sadece XML Serialization’ ın gerçekleştirilebildiğini görmekteyiz. Bu makalemizde .Net Compact Framework 2.0 platformu üzerinde Mobil Cihazlarda XML Serialization kavramı üzerine basit bir örnek geliştireceğiz.

Konun daha rahat anlaşılabilmesi açısından bu noktada örnek üzerinden gitmek daha faydalı olacaktır.

Standart bir C# Mobile 5.0 Smart Device Application projesi açarak işe başlıyoruz.

Amacımız XmlSerialization kullanarak datalarını mobil cihaz belleği üzerinde depolayan bir telefon defteri geliştirmek olacaktır.

Şekildeki formu tasarlayarak uygulamamıza devam ediyoruz :

Form üzerine yeni telefon bilgisi ekleneceği noktada kullanılacak olan iki adet metin kutusu, 3 adet buton ve iki adet kolon barındıran bir ListView kontrolü ekliyoruz.

Senaryoya göre kullanıcı uygulamayı çalıştırdığında Yükle button’ una basacak ; “eğer var ise” XML Dökümanı üzerinden ArrayList Deserialize edilecek ve içerisindeki tüm TelefonBilgisi objeleri ListView kontrolü içerisine eklenecektir.

İlk olarak kod tarafında şekildeki sınıfı oluşturuyoruz.

Şekilde bakıldığı zaman ilginç gelebilme ihtimali olabilecek tek metot BilgilerimdenListeElemaniGetir metodu olabilir. Metodun amacı Telefon bilgilerini içerisinde barındıran ve iki SubListViewItem içeren bir ListViewItem döndürmek olacaktır. Dönen objeyi ListView.Items.Add metoduna direk gönderdiğimiz noktada işimiz bitmektedir.

Şekildeki kod bloğu üzerinden devam ediyoruz :

Şekilde görülebileceği üzere Form’ umuz yüklendiği noktada global’ de tanımlanan xSER isimli XmlSerializer referansını yeni bir instance’ a eşitliyoruz.

Bu noktada dikkat edilmesi gereken nokta XmlSerializer nesnesinin constructer’ ında nesnenin serialize edebileceği tipleri belirlememiz gerekmektedir. Dikkat edilecek olursa ilk parametrede ArrayList tipi gonderilir iken ikinci parametrede TelefonBilgi isimli tip gönderilmiştir. Tipler doğru gönderilmediği taktirde nesnemiz ne serialize ne de deserialize işlemi gerçekleştirebilecektir.

Yükle button’ una basıldığında ise Mobil Cihazımızın kök klasörü içerisindeki TelefonData.xml isimli döküman aranamakta ; var ise açılmakta yok ise oluşturulmaktadır. Bir sonraki adımda açılan xml dökümanının boyutu incelenmekte ; 0 byte’ tan büyük ise XmlSerializer nesnemiz kullanılarak ArrayList deserialize edilmekte ; değil ise içi boş bir ArrayList objesi oluşturulmaktadır.

Son olarak Kaydetme ve Ekleme işlemlerini gerçekleştiren kod satırlarını belirliyoruz :

Yeni bir telefon eklendiğinde TelefonBilgi sınıfının yeni bir kopyası oluşturulmakta ve gerekli değerler gönderilmektedir. Bir sonraki adımda bu obje ArrayList içerisine eklenmekte ve eş zamanlı olarak ListView içerisine eklenmektedir.

Kaydet button’ una tıklandığında ise çalışan tek satır global’ de tanımlanmış olan XmlSerializer nesnesinin Serialize metodudur.

Hiç vakit kaybetmeden uygulamayı çalıştırıyoruz.

Uygulama ana ekran’ ı üzerinde ilk olarak Yükle button’ una basarak ArrayList’ in oluşmasını sağlıyoruz. İlk noktada TelefonData.xml dökümanı olmadığı için herhangi bir telefon datası gelmemektedir.

Bir sonraki adımda birkaç telefon datası ekliyoruz :

Dataları ekledikten sonra Kaydet Button’ una tıklıyoruz :

Ve hemen gidip mobil cihazımızın kök klasöründeki TelefonData isimli XML Dökümanımıza bakıyoruz :

Dosya başarıyla oluşturulmuş ve 510Byte’ lık bir boyuta sahip. Dosyayı hemen mobil cihaz emülatörümüz üzerinde açıyoruz :

Ve sonuç ! XmlSerializer kullanılarak ArrayList içerisindeki tüm objelerimiz ArrayList halinde xml dökümanına serialize edilmiş durumdadır. Hepsi bu kadar.

Bu makalemizinde sonuna geldik. Başka bir makalede daha görüşmek üzere.

.NET Compact Framework 2.0 - Mobil Cihazlarda System.Threading.Thread

Saturday, January 12, 2008 11:38:34 PM (GTB Standard Time, UTC+02:00)

Günümüz internet altyapısı incelendiğinde dağıtık uygulama senaryolarında işlemlerin belirlenen süreçler yerine anlık altyapı yoğunluğuna göre değişiklik gösterdiğini rahatlıkla anlayabiliriz. Bu noktada işlemin gerçekleştiği süreç esnasında uygulamanın o an görünen ekranının kilitlenmesi yerine Asenkron Mimari üzerinden bir uygulama dizaynı uyguladığımızda işlemin uygulama process’ i içerisinde farklı bir thread (şerit) üzerinden çalıştırıldığını ve işlemin çalıştığı süreç esnasında uygulamamızın normal seyrinde çalışıyor olmasını sağlayabiliriz. Bu noktada mimarinin uygulanabilmesi için farklı yöntemler söz konusudur. Bunlardan ilki işlemin uygulama içerisinde tanımlananan yeni bir thread içerisinde çalıştırılması iken bir diğeri ise –ki yönetimi çok kolay olmakla birlikte aslında arka tarafta aynı kapıya çıkmaktadır- delegelerin kullanılması ile sağlanan çözümdür. Bu makalemizde “Mobil Cihazlar” üzerinde threadleri kullanarak Asenkron Mimari üzerinde nasıl çalışacağız bu konu ile ilgili açıklayıcı bir örnek geliştireceğiz.

Örneğimize başlamadan önce basit bir senaryo üzerinde yoğunlaşalım. Mobil Cihazlarında kullanıldığı dağıtık bir uygulama senaryosu geliştirelim. Bir ilaç şirketinde çalışan ve sahada gün içerisinde merkez ile ellerindeki Pocket PC’ ler üzerinden iletişim kuran saha elemanları. Bu noktada elemanın bulunduğu nokta, baz istasyonu ile arasındaki bağlantının tutarlılığı v.b. gibi birçok etken bağlantı kurulduktan sonra gerçekleştirilen işlemin sonlandırma sürecini önemli ölçüde etkilemektedir. Bu noktada saha elemanının merkez nokta üzerinde bağlantı kurmak istediği zaman sürecinde bu işlem sonlanana kadar mobil cihazı üzerinde bulunan uygulamayı kilitlenmeden kullanabilmesi diğer işlerin gerçekleştirilmesi açısından önemli bir etkendir. İşte bu noktada Asenkron Mimari devreye girmektedir. Geliştirecek olduğumuz örnek uygulama üzerinde böyle bir uygulama senaryosunu gerçekleştiremediğimizden aynı kilitlenme ortamını oluşturabileceğimiz klişe bir örnek üzerinde konuyu inceleyeceğiz. 20000 adet sayının bir liste kutusuna yazdırıldığı süreci ele alalım. Aynı problem bu noktada yine yaşanacaktır. Sayıların listelenmesi süresince uygulamanın ana ekranı üzerinde herhangi bir işlem gerçekleştirilemeyecek ; belkide uygulama kilitlenip sonlanacaktır.

Daha fazla vakit kaybetmeden uygulamımızı geliştirmeye başlayalım. Konu ile ilgili çalışabilmek için bir C# Smart Device Windows Application projesi açıyoruz.

Bir sonraki adımda şekilde görülen basit formu tasarlıyoruz. Formumuzun üzerinde bir buton birde Liste kutusu kontrolü yerleştiriyoruz.

Amacımız listele butonuna bastığımız noktada liste kutusu içerisine 20000 adet sayının listelenmesi. Kulağa basit gelmekte olabilir. Ama sayı miktarının fazla olması bu noktada uygulamanın Asenkron Mimari üzerinden geliştirilmesi gerçeğini ortaya çıkarmaktadır. Bu noktada önce standart yaklaşımla şekildeki kod bloğunu geliştiriyoruz.

Sıra geldi uygulamamızı bu haliyle çalıştırmaya. F5’ e basarak projemizi çalıştırıyoruz ve Button’ a tıkladığımız zaman uygulamanın ana ekranının kitlediğini çok rahat bir şekilde analiz edebiliriz. Eğer bu noktada formumuzun üzerinde görsel açıdan farklı amaçlar için yerleştirilmiş Windows Form kontrolleri bulunsaydı bu kontroller üzerinde işlem sonlanana kadar kesinlikle bir değişiklik yapamayacak ; haliyle işlemin sonlanmasını beklemek zorunda kalacaktık. Uygulamanın çalışır haldeki görüntüsü şekildeki gibidir.

Şekildende farkedilebileceği üzere Scrollbar’ ın küçük olmasına rağmen (yani sayılar listelenmesine rağmen) ekranın kilitli görünümünden ötürü bu sayıları uygulamamız gösterememektedir. Peki çözüme nasıl ulaşacağız ?

Yazının başındada belirttiğimiz gibi Asenkron Mimari kullanarak bu probleme çözüm bulabilir. Bu noktada Asenkron Mimariyi bir uygulama üzerinde uygulayabilmemiz için birçok farklı yöntem bulunmaktadır. Fakat .NET Compact Framework’ ün ise bu konuda bazı sıkıntıları bulunmaktadır. Bunlardan en önemlisi uygulama geliştiriciler .NET Compact Framework üzerinde delegeleri kullanarak Asenkron Mimariye sahip uygulamalar geliştirememektedirler. Olaya bu açıdan baktığımızda kullanılabilecek tek yöntem System.Threading namespace’ i içerisinde bulunan Thread sınıfınından yararlanmak olacaktır.

Thread sınıfı, adından da anlaşılabileceği üzere Process’ lerin temel birimi olan Thread (Şerit)’ ler ile ilgili çalışmak üzere tasarlanmış bir sınıftır. Arkada tarafta işletim sistemi üzerinde tanımlı bir çok metodu Managed ortamda uygulama geliştiricilere çok daha kolay bir arayüz üzerinden sunmaktadır. Bu noktada .NET Compact Framework üzerinde tanımlı olan Thread sınıfı standart Thread sınıfının gerekli olan tüm metotlarını bünyesinde barındırmaktadır.

Sınıfın metot ve özelliklerine baktığımızda bir önceki paragrafta anlatıldığı üzere gerekli ve yeterli olan tüm yapıların hazır olarak geldiğini rahatlıkla anlayabiliriz.

Bu makalemizde örneklenen uygulamada yaşanan sorun daha öncede anlatıldığı üzere, uygulama process’ i başlatıldığında bu process’ in içerisinde o noktadan sonra yürütülecek olan tüm işlemlerin çalıştırılacağı Main (Ana) bir Thread istesekte istemesekte oluşturulmaktadır. Application.Run metodu ile uygulamamızın başlayan yaşam süreci içerisinde işletim sistemi üzerinen gelen mesajlar sırasıyla işletilmektedirler. Bu noktada yaşanan problem döngü içerisinde “döngü sonlanana kadar” her yeni değerde yeni bir mesaj gelmekte ; işletilmekte ve haliyle uygulama içerisinde gönderilen diğer mesajlar bekletilmektedirler. Bunun sonucunda ise işlem sonlanana kadar uygulama ekranımız “kilitlenmektedir”. Amacımız bu işlemleri Main (Ana) thread’ in dışında yeni bir Worker (İşçi) thread kullanarak uygulamanın temel thread’ i dışında çalıştırarak ; uygulama ana ekranının gönderilen diğer mesajların çalıştırabilmesini ; başka bir deyişle kitlenmemesini sağlamaktır. Hiç vakit kaybetmeden makalemize kaldığımız yerden devam edelim. Amacımız bir önceki cümlede de ifade ettiğimiz üzere işi gerçekleştirecek Worker (İşçi) bir thread tanımlamak olacaktır.

Kod ile ilgili “ayrıntılı” bir açıklamanın bu noktada gerekli olduğundan satırların numaralandırılmış olması daha doğru olacaktır.

İlk olarak 18 numaralı satır üzerinden geliştirdiğimiz kod bloğunu açıklamaya geçelim. Bu satır içerisinde System.Threading.Thread sınıfının th isminde null bir referansını oluşturmaktayız. Bu null referansı Form1_Load metodu içerisinde System.Threading.Thread sınıfının bir instance’ ına eşitliyoruz. Ki bakacak olursak bütün olay bu satırda ; yani 21 numaralı satır içerisinde halledilmektedir.

Thread sınıfının Constructer’ ına baktığımızda, sınıf, uygulama geliştiriciden System.Threading.ThreadStart tipinde bir delege instance’ ı istemektedir.

Sınıfın bu delegeyi istemesinin temel sebebi çalıştıracak olduğu metodun adresine ihtiyaç duyduğu zaman çekebilmesi içindir. Bu noktada ThreadStart delegesi sadece “parametre almayan” ve “void geri dönüş değerine sahip” bir metodu adresleyebilmektedir. Bu sebeple 26. Satırdan itibaren Saydir() isimli parametre almayan ve void geri dönüş değerine sahip bir metot tanımlanmıştır. Döngümüz ise bu metot içerisinde ise çalıştırılmaktadır. Bu noktada 30. Satırda kontrolün Items koleksiyonu içerisindeki standart Add metodunun neden kullanılmadığına değinmek çok doğru olacaktır.

Bilindiği üzere asenkron mimariye sahip uygulamalarda Worker (İşçi) thread üzerinden farklı bir thread üzerinde oluşturulmuş bir objenin herhangi görsel bir değerini değiştirememekteyiz. Böyle bir durumda CrossThreadOperationException tipinde ifade edilebilecek bir hata kaçınılmaz olacaktır. Bu noktada kontrolün Invoke metodu ile işlemi lstSAYILAR isimli Liste kutusununu oluşturulduğu Main (Ana) thread üzerine geçirmekte ; sayı ekleme işlemini bu lokasyonda gerçekleştirmekteyiz.

Biraz daha yakından incelediğimizde ise Invoke metodu da Thread sınıfının istediği türe benzer bir türden çalıştıracak olduğu metodun adresini alabilecek bir delege istemektedir. Fakat bu noktada elimizde hazır bir delege bulunmadığından ListBox kontrolünün Items koleksiyonu içerisinde bulunan Add metodu ile aynı geri dönüş değeri ve parametre yapısına sahip bir deleyi kendimiz oluşturup, bunun bir kopyasını lstSAYILAR.Items.Add metodunu adresleyerek Invoke isimli metoda değer olarak göndermekteyiz.

Tüm bu adımlar başarılı bir şekilde gerçekleştirdikten sonra 36. Satırda yani btnSAYDIR button’ una tıkladığımızda th isimli Thread objesi referansı üzerinden Thread’ i çalıştırmaya başlatıyoruz. Hepsi bu kadar !

Uygulamayı çalıştırıp Saydır button’ una bastığımız zaman sonuç tek kelimeyle mükemmel ! Saydırma işlemi devam ederken ScrollBar hareket ettirilebilir durumda olmakla birlikte ekran üzerindeki diğer kontroller işlemin bitmesini beklememektedir ; kullanıma açık durumdadır !

Bu makalemizde Mobil cihazlar üzerinde System.Threading.Thread sınıfını kullanarak asenkron işlemler nasıl gerçekleştirilir bunun üzerinde ayrıntılı bir örnek geliştirdik.

Başka bir makalede daha görüşmek üzere.

.Net Compact Framework 2.0 – Mobil RSS Okuyucu

Saturday, January 12, 2008 11:37:58 PM (GTB Standard Time, UTC+02:00)

Son günlerde birçok blog, forum, haber ve benzeri amaçlar üzerine kurulmuş internet siteleri ya da  portalları üzerinde RSS yayını adı altında bir servis standart internet ziyaretçilerine hizmet vermektedir.   ikonu bulunan sitelerde kullanıcılar diledikleri taktirde bu RSS kaynaklarını RSS destekli uygulamalar üzerine kayıt ettirebilmekte ; site üzerinden herhangi bir noktada gerçekleştirilen bir güncelleme ile ilgili bu RSS kaynağından ; dolayısıyla RSS işleyen uygulamalar üzerinden haberdar edilmektedirler. Peki nedir bu kadar meşhur olan bu RSS ? O’ nu bu kadar kullanılması cazip kılan kavramlar nelerdir ? Bu noktada biraz bu soruların cevaplarını arayalım.

Öncelikle şunu belirtmek gerekirki RSS, belli bir zaman süreci içerisinde isim açılımı bakımından belli bir değişime uğramıştır. İlk standartatize versiyonundan itibaren RSS internet üzerinde ;

  • Rich Site Summary (RSS 0.91)
  • RDF Site Summary (RSS 0.9 and 1.0)
  • Really Simple Syndication (RSS 2.0.0)

şeklinde ifade edilebilecek farklı akronimler üzerinden tanımlanmaktadır.

RSS, temel amacı bakımından, “bu kaynağı sunan internet sitelerinin bu kaynak üzerinden sunulan içeriklerini daha rahat takip edebilmek için oluşturulmuş standartize bir XML dökümanı & XML Formatı” olarak ifade edilebilmektedir.

RSS kaynağı üzerinden içeriklerini dağıtan internet siteleri dünya üzerinde geliştirilmiş olan neredeyse tüm RSS okuyucuları için standartize edilmiş bazı temel kuralları uygulamış olmaları gerekmektedir.

Bu temel kuralların başında RSS kaynağı üzerinden yayını yapılan XML dökümanının bazı temel element isimlerine sahip olmaları gerekmektedir. Bu temel element isimleri üzerinden RSS kaynağınızı dünya üzerindeki neredeyse birçok RSS okuyucusu destek verebilir ; ziyaretçiler bu uygulamaları üzerinden siteniz üzerinden yayını yapılan RSS kaynaklarına erişebilirler.

Peki nedir bu temel kurallar diye sorarak makalemizin teorik kısmına bu noktada devam edelim. Bir önceki paragrafta doğru bir RSS dökümanı içerisinde mutlak surette olması gereken bazı elementlerden bahsetmiştik. Bu elementler dünya üzerinde birçok RSS kaynağı tarafından kabul edilmiş ; birçok uygulama tarafından da tanınmaktadır.  Bu temel element isimlerini kısaca açıklamak gerekirse ;

Bir RSS dökümanı içerisinde bulunması muhtemel XML Tag isimlerini ifade edebilmek açısından örnek bir RSS çıktısı görüntülemek daha doğru olacaktır. Ekran görüntüsü makalemizde de kullanacak olduğumuz Hürriyet Gazetesi RSS Kaynağı içerisindeki bir haberin RSS çıktısıdır.

Şekilden de anlaşılabileceği üzere, üzerinde çalışacak olduğumuz RSS kaynağının adresi, logosu ve açıklamasıyla ilgili XML Tag’ lerinin altında standartize ve tekrar ederek giden bir Tag betiği bulunmaktadır.

Her bir haber <item></item> tag’ leri ile ifade edilirken her <item></item> tag’ leri arasında bilginin başlığı, varsa açıklaması, kaynak adresi ve yayınlanma tarihi bulunmaktadır.

Bu noktada belirtilmiş olması gereken en önemli nokta ise bu sayılan tag’ lerin birçok RSS kaynağında standart bir şekilde bulunacağı ; spesifik durumlarda yeni tag’ lerinde eklenebileceği olduğudur.

Evet, RSS ile ilgili temel seviyede bilgi sahibi olduktan sonra yavaş yavaş makalemizin asıl konusuna doğru geçiş yapalım. Amacımız dünya üzerindeki standart bir RSS okuyucusunun yaptığı gibi yukarıda örneği ifade edilen bir RSS kaynağını standartların dışında çok farklı bir ortamdan ; “Mobil Cihazlar” üzerinden okuyup kullanıcıya gün içerisinde yolda ya da bulunduğu herhangi bir lokasyonda haberleri takip etmesini sağlayacak bir Mobil RSS Okuyucusu geliştireceğiz.

Bu makale süresince .Net Compact Framework 2.0 üzerinde birçok farklı kavram üzerinde bilgi sahibi olup böyle bir uygulama içerisinde uygulayarak tecrübe sahibi olacağız.

Hiç vakit kaybetmeden uygulama senaryomuz üzerinde bilgi sahibi olalım.

Amacımız Mobil Cihaz kullanıcılarının diledikleri her noktada Hürriyet Gazetesinin RSS Kaynağı üzerinden farklı kategoriler üzerinden sunulan haber başlıklarına ulaşabilmeleri için bir RSS Okuyucusu oluşturmak olacaktır. Bu noktada uygulama tasarımı bakımından birtakım problemlere karşın bazı önlemler almamız gerekmektedir.

Üzerinde çalışacak olduğumuz kavram internet erişiminin o anki performansı ile doğru orantılı olarak çalışacağından uygulamayu kullanacak olan kullanıcılar RSS Servisine istekte bulunduğunda sonuç gelene kadar beklememesi gerekmektedir. Bu noktada işin içerisine Asenkron Mimari girmektedir. Uygulamamız içerisinde uzak noktaya yapacak olduğumuz çağrıların tümü “Asenkron Mimari” üzerinden geliştirilecektir. Böylece tek bir makale üzerinden Xml, Threading ve RSS kavramlarını öğrenmiş olacağız.

Hiç vakit kaybetmeden makalemizin konusunu oluşturan uygulamamızı geliştirmeye başlayabiliriz. Bu noktada uygulamamız Windows Mobile 5.0 işletim sistemi ile çalışan Pocket PC cihazları için geliştirilecektir. Bunun için sistemimize Mobile 5.0 SDK’ nın yüklü olduğunu varsayarak bir C# Smart Device Mobile 5.0 Projesi açıyoruz.

Bir sonraki adımda ise yavaş yavaş uygulama ekranımızı tasarlamaya başlayabiliriz. Bu noktada uygulama içerisinde gerçekleştirmek istediğimiz senaryoda kullanıcı Hürriyet Gazetesinin RSS Kaynaklarıyla ile ilgili kategorileri bir ComboBox içerisinden seçip ; bir sonraki adımda ComboBox’ ın altında bulunan ListView kontrolü içerisinde kolon bazlı bir yapı üzerinden seçilen kategorideki haberleri görüntüleyecektir. İşin programatik kısmına geçmeden önce bu noktada Hürriyet Gazetesinin RSS Kaynağı ile ilgili adreslerden bahsetmek daha doğru olacaktır.

Hürriyet Gazetesi RSS Kaynağı olarak farklı adresler üzerinden farklı kategorilerde kaynaklar sunmaktadır.

http://dosyalar.hurriyet.com.tr/rss/ adresinde ifade edildiği üzere Hürriyet Gazetesi RSS Servisi şekildeki adresler ve katerogiler üzerinden kullanıcılara RSS Kaynağı sunmaktadır.

Amacımız bu noktada kullanıcıya ComboBox içerisinden şekilde sol tarafta sıralanmış olan kategorileri seçtirtmek ; bir sonraki adımda ise sağ tarafta bulunan adresler üzerinden RSS kaynağını almak olacaktır. Bu noktada şekildeki form tasarımı üzerinden uygulamamıza devam ediyoruz :

Şekildende anlaşılabileceği üzere form üzerine Bir ComboBox, View Özelliği “Details” olarak belirtilmiş bir ListView ve En alta seçili haber ile ilgili detay bilgiyi gösterecek “ReadOnly” bir metin kutusu ekledik. Bu noktada standart olarak eklenen MainMenu kontrolü içerisine iki adet MenuItem eklemiş bulunmaktayız.

Ayrıca şunuda belirtmemiz gerekmektedirki Details görünümünde çalıştırılacak olan ListView kontrolümüzün içerisine RSS Kaynağı üzerinden getirilen bilgilerin Başlık Ve Tarih bilgilerini ekran üzerinde gösterebilmemiz için iki adet kolon eklemiş bulunmaktayız.