KMRT BSRN

"Hiç kimsenin ilgisine ihtiyaç duymadığın gün olgunlaşırsın. Hiç kimseden beklentiye girmediğin gün yara almazsın. Ve hiç kimseye bağımlı kalmazsan kazanırsın." OSHO

C# – Add-In Tabanlı Uygulama Geliştirme

Yorum bırakın


 

Geliştirilen uygulamalarda en popüler tekniklerden biri eklentilere destek vererek uygulamanın son kullanıcılar tarafından da geliştirilebilmesine olanak tanınmasıdır. Bu konuda en güzel örneklerden biri Mozilla Firefox internet tarayıcısının bu yöndeki başarısı. Microsoft’un internet explorer’ına karşı kullanım atağı elde etmesinde mutlaka tek neden olmasada en önemli 3 özellikten biri olduğuna inanıyorum. Çünkü her kullanıcıya yönelik çok faydalı eklentilere sahip. Bu yapı beni çok etkilemiştir. Bir yazılım geliştirici olarak eklenti tabanlı uygulama geliştirme tekniği bence çok etkileyici ve faydalı bir yöntem. Uygulamanın çekirdek yapısına dokunmadan, çekirdek yapısını açıp kod geliştirmesi yapıp derleme işlemine girmeden uygulamanıza ek özellikler katabileceğiniz bir yöntem. Bir diğer faydası uygulamanızın son kullanıcılar tarafından da geliştirilebilirliğini sağlayarak çok hızlı bir gelişimin içinde popülerleşmesini sağlamasıdır. Burada hemen akla şu soru geliyor. Peki ya kullanıcılar uygulamanın yapısını bozarsa, işte bu noktada diğer bir güzel özellik, tamamen sizin erişimine izin verdiğiniz miktarda bu eklenti geliştirilmesine izin verilmesidir.

Eklenti geliştirmeye örnek olarak MSN Messenger’a eklenti geliştirebilirliliğini incelemenizi tavsiye ederim. .Net ile çok pratik ve zevkli bir şekilde kullandığınız messenger ‘a eklenti geliştirebilirisiniz. Bu konuda Işıl Orhanel’in makalesini okumanızı tavsiye ederim. MSN’nin bize sunduğu şekilde bir eklenti tabanlı uygulama geliştirilmesini kısaca anlatacağım..

Visual Studio .Net 2008 ‘de “Blank Solution” açarak Solution’ımıza projelerimizi ekleyeceğiz. “PluginSolution” isimli bir blank Solution açıyorum. bu solution’ınımız 3 adet proje içerecektir.

 

Bu projelerden;

1 tanesi “Windows Application Projesi” (WinApp ismini vereceğim.)

1 tanesi “Class Library Projesi” (AppClient ismini vereceğim.)

1 tanesi “Class Library Projesi” (Plugin ismini vereceğim.)

 

Yanda bu yapıyı görebilirsiniz. Bu çözümümüzde(solution) oluşturduğumuz bu projeler şu işe yarayacaklar. WinApp isimli windows application projemiz bizim çekirdek uygulamamızı oluşturuyor. Yani Görselliği olan kullanıcının kullanacağı uygulamadır.

Plugin projesi, WinApp’den tamamiyle bağımsız bir DLL projesidir. Amacımız bu DLL projesinde oluşan Plugin.dll isimli DLL’i , WinApp uygulamasının bulunduğu konumda bir “Plugin” isimli klasör oluşturarak buraya kopyalamaktır. Bu işlemin ardından WinApp uygulamasının “Form_Load” olayında bu klasör altını kontrol ederek, var olan DLL’lerin kullanılmasını sağlayarak windows uygulaması içinde DLL içinde yazılmış kodların çalıştırılmasını sağlamaktır.

AppClient projesi ise, WinApp ve Plugin projelerinin birbirini tanımasını sağlayarak veri akışını sağlayan ortak bir nesne türünü oluşturmaktadır. Yani köprü görevi görmektedir.

Projelerin birbiri ile ilişkisini anlatan şemayı altta bulabilirsiniz.

Şimdi WinApp uygulamamızdaki Form1’e 2 adet buton ekleyelim..

Burada amacımız şöyle;

2 adet butonumuz vardır. Bu butonların isimlerini önemsemeyin. Rastgele verilmiş isimlerdir. yapmak istediğimiz bu butonlara basıldığında bir mesaj kutusu(MessageBox) içinde tıklanan buton ile ilgili bilgi vermektir. Buraya kadar herşey tamam, yani çift tıkla butona git kodunuz yaz der gibisiniz. 🙂 Evet orası öyle ama asıl yapmak istediğim bu butonların Click olayında “Plugin” isimli projemiz üzerinden de geliştirme yaparak bir işlem yapılabilmesini sağlamaktır. Fakat Plugin projemiz tamamen ayrı bir proje ve “references” yoluyla hiçbir şekilde WinApp uygulamasına eklemeden Plugin’e ulaşmak ve yazılmış kodun çalıştırılmasını sağlamaktır.

Bu işlem için yani Plugin projemizin uygulamamızı tanıması ve yapılmasını istediğimiz işlemi ya da diğer bir değişle o andaki işlemi anlaması ve plugin projesinde geliştirdiğimiz kodun çalışması için ortak nesne türünden faydalanacağız. Bu da AppClient idi.

İlk olarak bu prjemizi geliştirelim. Bu projemizde bir interface kullanacağım ve interface içinde sadece Initialize isimli bir metod içerecek. Bu interface’i implement’e eden class için bu metod oluşturulacak ve parametre olarak bir WinApp uygulamamızda oluşturduğumuz nesneyi parametre olarak alacaktır. Kodumuz üzerinde bu işlemi daha iyi görebiliriz.

 

AppClient projemizde;

IClient.cs isimli bir interface oluşturuyoruz..

using System;
using System.Collections.Generic;
using System.Text;
 
namespace AppClient
{
    public interface IClient
    {
        void Initialize(AppClient.Client client);
    }
}

 

Client.cs isimli bir class oluşturuyoruz.

using System;
using System.Collections.Generic;
using System.Text;
 
namespace AppClient
{
    public class Client
    {
        //İstediğimiz işlemlerde kullanmak için kullanacağımız özelliklerimiz..
        public string Name { get; set; }
        public string Message { get; set; }
        public DateTime NowDateTime { get; set; }
 
        //Dışarıdan erişilmesini istediğimiz metodlar..
        public event EventHandler OutGoingMessageEvent;
        public event EventHandler InComingMessageEvent;
 
        //Yapıcı metodumuz.
        public Client()
        {
 
        }
 
        //OutGoingMessageEvent olayını tetikleyen metodumuz.. 
        //Dışarıdan bu metodu çağırarak bu olayın tetiklenmesini sağlayacağız.
        public void FireOutGoingMessageEvent(object sender, EventArgs e)
        {
            OutGoingMessageEvent(sender, e);
        }
 
        //InComingMessageEvent olayını tetikleyen metodumuz.. 
        //Dışarıdan bu metodu çağırarak bu olayın tetiklenmesini sağlayacağız.
        public void FireInComingMessageEvent(object sender, EventArgs e)
        {
            InComingMessageEvent(sender, e);
        }
    }
}

 

Yukarıdaki kodu açıklayalım. Burada Client isimli bir sınıf oluşturduk. Bu sınıf içinde iki adet Event(olay) var. İki adet metodumuz var. Bu iki adet metod, olayların tetiklenmesini sağlamaktadır. Amacımız bu Client nesnesini WinApp içinde bir değişken olarak kullanarak bir nesne oluşturmamız ve butonların tıklanmasında Client içindeki olayların tetiklenmesini sağlamaktır. Olay biraz karışıklaşmaya başladı gibi gelebilir. Bu olayı böyle anlatmak biraz güç çünkü olayı bir bütün olarak yansıtmak gerekmekte. Bu nedenle aşağıdaki şemada olayı daha detaylı görebilirisiniz.

Sanırım yukardaki şema olayı gayet iyi bir şekilde hafızanızda canlanmasını sağlamıştır. Böylece elimizde artık köprü görevi gören AppClient projesinide kullanarak(Client ve IClient nesnesini kullanarak) yukardaki şemaya uygun işleyişimizi kodlayabiliriz.

Plugin projemize References kısmından AppClient.dll’ini ekliyoruz. Ardından projemize bir adet Plugin.cs isimli bir class ekliyoruz.

Plugin.cs

 

Plugin.cs class’ımız gördüğünüz gibi “AppClient.IClient” interface’ini implement etti. Böylece “Initialize” metodu oluştur. Bu metod dışardan client nesnesi alıyor. İşte biz bu nesne içindeki event(olay)’ları kullanacağız. Çünküyukardaki şemadaki gibi WinApp içinde de bu nesne deki olaylar butonlar tıklandığında fırlatılacak. Plugin.cs içinde Initialize metodunda gelen client nesnesine “this.myClient.OutGoingMessageEvent” ve “this.myClient.InComingMessageEvent” ifadeleri ile olaylar tanımlanıp olaylarda çalışacak kod geliştirilir. MessageBox nesnesine ulaşamazsanız, projemizde “References” bölümünden tekrar yararlanıp “.NET” sekmesinden “System.Windows.Forms” referansını ekleyiniz.

Plugin projemizi derliyoruz ve derleme sonucu oluşan Plugin.dll dosyamızı proje klasörü içinde “Bin –> Debug” altına giderek kopyalıyoruz. WinApp projesinde “Bin –> Debug” altına “Plugin” isimli bir klasör oluşturuyoruz ve içine Plugin.dll ’ i kopyalıyoruz. Gördüğünüz gibi Plugin.dll dosyamızı “References” kısmıdan değil bir dosya olarak WinApp uygulaması klasörü altına koyduk.

Şimdi sıra WinApp projesinde Form1.cs kodunu yazalım. Bu arada WinApp uygulamasının Plugin.dll ile haberleşebilmesinde kullanacağımız AppClient.dll referansını “References” bölümünden eklemeyi unutmayın !

Form1.cs

Bu kod içinde en kritik yer Run-Time(çalışma zamanında-kod çalışırken) ‘da Plugin.dll ‘indeki Plugin.cs class’ından bir nesne oluşturulmasıdır.(Form_Load metodu içinde)

 

    //Load Plugin Assembly
    string appPath = Application.StartupPath + "\\Plugin\\Plugin.dll";
 
    //Plugin.dll nesnesi Run-Time'da Instance'ı oluşturulur ve 
    //this.myClient değişkeni parametre olarak Plugin.dll'e gönderilir.
    Assembly asm = System.Reflection.Assembly.LoadFile(appPath);
    object obj = asm.CreateInstance("Plugin.Plugin");
    ((AppClient.IClient)obj).Initialize(this.myClient);

 

Reflection tekniği kullanılarak Plugin.dll ‘in konumu ile Assembly nesnesi oluşturulur. Ardından bu Assembly nesnesinin CreateInstance(); metoduna class’ın tam namespace yolu verilerek(Plugin.Plugin) object tipinde nesnesinin oluşturulmasını sağladık(obj). obj nesnesi aslında IClient tipini tanıyor. Çünkü Plugin.dll içinde Plugin.cs class’ımızı AppClient.IClient tipinden inherit(miras) aldırmıştık. obj nesnesini IClient tipine cast ediyoruz. Böylece Initialize metoduna erişmiş olduk. Sonra form açılışında oluşturduğumuz myClient nesnesini parametre olarak Plugin.dll’e gönderiyoruz. Böylece Plugin.dll Initialize metodunda kodlandığı gibi bu nesneyi Private myclient değişkenine aktarıp saklıyor.

Böylece WinApp açılışında oluşan bir nesneyi hem WinApp içinde hem de Plugin.dll içinde kullanabilmeyi sağladık(myClient nesnesi). myClient nesnesine Form_Load kısmında 2 adet olay tanımlı bunlar WinApp içinde çalışacak metodlar. Aynı zamanda biz Plugin.cs içinde Private myClient değişkenimize 2 adet olay tanımlamıştık. Yani myClient nesnemizin 4 adet olayı olmuş oldu. 2 adet OutGoingMessageEvent ve 2 adet InComingMessageEvent .

Son işlemimiz bu olayların WinApp içinde butonlara tıklanınca çalışmasını sağlamak. Yani olayları tetiklemek. Bunu yapan kod form1.cs içinde şu satırlar;

    //FireOutGoingMessageEvent butonu tıklanınca this.myClient değişkenimizdeki 
    //olayı fırlatmaya yarayan metodumuz çağırılıyor.
    private void button1_Click(object sender, EventArgs e)
    {
        //Plugin.dll içinde myClient.OutGoingMessageEvent olayı çalıştırılır.
        this.myClient.FireOutGoingMessageEvent(this.myClient, e);
    }
 
    //FireInComingMessageEvent butonu tıklanınca this.myClient değişkenimizdeki 
    //olayı fırlatmaya yarayan metodumuz çağırılıyor.
    private void button2_Click(object sender, EventArgs e)
    {
        //Plugin.dll içinde myClient.InComingMessageEvent olayı çalıştırılır.
        this.myClient.FireInComingMessageEvent(this.myClient, e);
    }

 

myClient nesnesindeki olayları tetikleyen metodları çağırıyoruz ve isteğimize bağlı olarak myClient nesnesini o metoda parametre gönderiyoruz. Bu parametre kısmı o kadar önemli değil. Önemli olan myClient içinde “FireOutGoingMessageEvent” ve “FireInComingMessageEvent” metodlarını çağırabilmemiz ve bu metodlar içerisinde olayları tetikleyerek. myClient nesnemize bağlı 4 adet olayında çalışmasını sağlar. Evet bir üst kısımda bahsettiğimiz olayların tetiklenmesini sağlamış olur.

WinApp uygulamasını çalıştırdığınızda MessageBox ‘lardaki bilgilerden WinApp ve Plugin içinde ayrı ayrı çalışan metodları görebilirsiniz.

Böylece projemizi tamamladık. Burada üstüne vura vura bir kısmı tekrarlamak istiyorum. Şu anda Plugin projemiz tamamen WinApp’den bağımsızdır. Yani yeni bir VS.NET projesi açarak AppClient.dll ‘i projemize referans edip, Plugin.cs class’ı ekleyip bunu AppClient içindeki IClient tipinden inherit ederek oluşturduğumuz Plugin.dll ‘i programın bulunduğu klasördeki “Plugin” klasörü içine kopayalarak farklı işlerin yapılmasını sağlayabilirsiniz.

WinApp uygulamamızdan bağımsız ve bize sunduğu Property(özellikler), event(olaylar) sayesinde eklentimizi geliştirebiliriz ve kullanılmasını sağlayabiliriz. Bu yapıyı daha da geliştirerek birden fazla DLL’i okuması ve instance’ını oluşturmasını ve çalıştırması sağlanabilir. Böylece uygulamanız eklenti tabanlı geliştirilebilen bir uygulama olur. Bir de bu geliştirme olayı için geliştiricilere yapabilecekleri işlemleri anlatan bir Yardım(Help) dosyası eklerseniz…

Daha ne olsun, bundan iyisi can sağlığı 🙂

Hepinize kolay gelsin,

İyi Çalışmalar.

Proje dosyası için tıklayınız.

Reklamlar

Yazar: K. Murat BAŞEREN, MBA, MCP

I am a senior software developer, MCP, consultant, blogger, former chemist and software trainer. My interests range from software developer to technology. I am also interested in web development, education, and coffee.

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s