Hiç dotNET ‘te yer alan bir tipin üyelerini öğrenebilmek istediniz mi? ÖrneÄŸin var olan bir dotNET sınıfının veya sizin kendi yazmış olduÄŸunuz yada bir baÅŸkasının yazdığı sınıfa ait tüm üyelerin neler olduÄŸuna programatik olarak bakmak istediniz mi? Â
İşte bugünkü makalemizin konusu bu. Herhangi bir tipe (type) ait üyelerin neler olduÄŸunu anlayabilmek. Bu amaçla, Reflection isim uzayını ve bu uzaya ait sınıfları kullanacağız. BildiÄŸiniz gibi .NET ‘te kullanılan her ÅŸey bir tipe aittir. Yani herÅŸeyin bir tipi vardır. Üyelerini öğrenmek isteÄŸimiz bir tipi öncelikle bir Type deÄŸiÅŸkeni olarak alırız. (Yani tipin tipini alırız. Bu nedenle ben bu tekniÄŸe Tip-i-Tip adını verdim ). Bu noktadan sonra Reflection uzayına ait sınıfları ve metodlarını kullanarak ilgili tipe ait tüm bilgileri edinebiliriz. Küçük bir Console uygulaması ile konuyu daha iyi anlamaya çalışalım. Bu örneÄŸimizde, System.Int32 sınıfına ait üyelerin bir listesini alacağız. İşte kodlarımız;Â
|
using System;
namespace ReflectionSample1
{
     class Class1    Â
     {
          static void Main(string[] args)
          {
               Type tipimiz=Type.GetType(“System.Int32″);/* Öncelikle String sinifinin tipini ögreniyoruz. */
               System.Reflection.MemberInfo[] tipUyeleri=tipimiz.GetMembers(); /* Bu satir ile, System.String tipi içinde yer alana üyelerin listesini Reflection uzayinda yer alan, MemberInfo sinifi tipinden bir diziye aktariyoruz. */
               Console.WriteLine(tipimiz.Name.ToString()+” sinifindaki üye sayisi:”+tipUyeleri.Length.ToString());/* Length özelligi, MemeberInfo tipindeki dizimizde yer alan üyelerin sayisini, (dolayisiyla                System.String sinifi içinde yer alan üyelerin sayisini) veriyor.*/
               /* Izleyen döngü ile, MemberInfo dizininde yer alan üyelerin birtakim bilgilerini ekrana yaziyoruz.*/
               for(int i=0;i<TIPUYELERI.LENGTH;++I)    Â
               {
                    Console.WriteLine(i.ToString()+”. üye adi:”+tipUyeleri[i].Name.ToString()+”||”+tipUyeleri[i].MemberType.ToString()); /* Name özelligi üyenin adini verirken, MemberType özelligi ile, üyenin tipini aliyoruz. Bu üye tipi metod, özellik, yapici metod vb… dir.*/
               }
          }
     }
} |
Â
Uygulamayı çalıştırdığımızda aşağıdaki ekran görüntüsünü elde ederiz.

Åžekil 1. System.Int32 sınıfının üyeleri.Â
Üye listesini incelediÄŸimizde 15 üyenin olduÄŸunu görürüz. Metodlar, alanlar vardır. Ayrıca dikkat ederseniz, Parse , ToString metodları birden fazla defa geçmektedir. Bunun nedeni bu metodların overload ( aşırı yüklenmiÅŸ ) versiyonlara sahip olmasıdır.Â
Kodları incelediÄŸimizde, System.Int32 sınıfına ait tipleri GetMembers metodu ile, System.Reflection uzayında yer alan MemberInfo sınıfı tipinden bir diziye aldığımızı görürüz. İşte olayın önemli kodları bunlardan oluÅŸmaktadır. MemberInfo dışında kullanabaileceÄŸimiz baÅŸka Reflection sınıflarıda vardır. Bunlar;Â
|
ConstructorInfo
|
Tipe ait yapıcı metod üyelerini ve bu üyelere ait bilgilerini içerir.
|
|
EventInfo
|
Tipe ait olayları ve bu olaylara ait bilgileri içerir.
|
|
MethodInfo
|
Tipe ait metodları ve bu metodlara ait bilgileri içerir.
|
|
FieldInfo
|
Tip içinde kullanılan alanları ve bu alanlara ilişkin bilgileri içerir.
|
|
ParameterInfo
|
Tip içinde kullanılan parametreleri ve bu parametrelere ait bilgileri içerir.
|
|
PropertyInfo
|
Tip içinde kullanılan özellikleri ve bu özelliklere ait bilgileri içerir.
|
Tablo 1. Reflection Uzayının DiÄŸer Kullanışlı SınıflarıÂ
Åžimdi bu sınıflara ait örneklerimizi inceleyelim.Â
Bu kez bir DataTable sınıfının üyelerini inceleyeceÄŸiz. Örnek olarak, sadece olaylarını ve bu olaylara iliÅŸkin özelliklerini elde etmeye çalışalım. Bu örneÄŸimizde, yukarıda bahsettiÄŸimiz tip-i-tip tekniÄŸini biraz deÄŸiÅŸtireceÄŸiz. Nitekim bu tekniÄŸi uygulamamız halinde bir hata mesajı alırız. Bunun önüne geçmek için, bir DataTable örneÄŸi (instance) oluÅŸturup bu örneÄŸin tipinden hareket edeceÄŸiz. Dilerseniz hemen kodlarımıza geçelim.Â
|
using System;
namespace ReflectionSample2
{
     class Class1
     {
          static void Main(string[] args)
          {
               System.Data.DataTable dt=new System.Data.DataTable(); /* Bir DataTable örnegi(instance) yaratiyoruz.*/
               Type tipimiz=dt.GetType(); /* DataTable örnegimizin GetType metodunu kullanarak, bu örnegin dolayisiyla DataTable sinifinin tipini elde ediyoruz. */
               System.Reflection.MethodInfo[] tipMetodlari=tipimiz.GetMethods(); /* Bu kez sadece metodlari incelemek istedigimizden, GetMethods metodunu kullaniyor ve sonuçlari, MethodInfo sinifi tipinden bir diziye aktariyoruz.*/
               Console.WriteLine(tipimiz.Name.ToString()+” sinifindaki metod sayisi:”+tipMetodlari.Length.ToString()); /* Metod sayisini Length özelligi ile aliyoruz.*/
               /* Döngümüzü olusturuyor ve Metodlarimizi bir takim özellikleri ile birlikte yazdiriyoruz.*/
               for(int i=0;i<TIPMETODLARI.LENGTH;++I)
               {
                    Console.WriteLine(“Metod adi:”+tipMetodlari[i].Name.ToString()+” |Dönüs degeri:”+tipMetodlari[i].ReturnType.ToString()); /* Metodun ismini name özelligi ile aliyoruz. Metodun dönüs tipini ReturnType özelligi ile aliyoruz. */
                    System.Reflection.ParameterInfo[] prmInfo=tipMetodlari[i].GetParameters();
                    /* Bu satirda ise, i indeksli metoda ait parametre bilgilerini GetParameters metodu ile aliyor ve Reflection uzayinda bulunan ParameterInfo sinifi tipinden bir diziye aktariyoruz. Böylece ilgili metodun parametrelerine ve parametre bilgilerine erisebilicez.*/
                    Console.WriteLine(“—–Parametre Bilgileri—–”+prmInfo.Length.ToString()+” parametre”);
                    /* Döngümüz ile i indeksli metoda ait parametrelerin isimlerini ve tiplerini yazdiriyoruz. Bunun için Name ve ParameterType metodlarini kullaniyoruz.*/
                    for(int j=0;j<PRMINFO.LENGTH;++J)
                    {
                         Console.WriteLine(“P.Adi:”+prmInfo[j].Name.ToString()+” |P.Tipi:”+prmInfo[j].ParameterType.ToString());
                    }
                    Console.WriteLine(“—-”);
               }
          }
     }
} |
Â
Åžimdi uygulamamızı çalıştıralım ve sonuçlarına bakalım.Â

Åžekil 2. System.Data.DataTable tipinin metodları ve metod parametrelerine ait bilgiler.Â
Reflection teknikleri yardımıyla çalıştırdığımız programa ait sınıflarında bilgilerini elde edebiliriz. İzleyen örneÄŸimizde, yazdığımız bir sınıfa ait üye bilgilerine bakacağız. Â
Üyelerine bakacağımız sınıfın kodları;Â
|
using System;
namespace ReflectionSample3
{
     public class OrnekSinif
     {
          private int deger;
          public int Deger
          {
               get
               {
                    return deger;
               }
               set
               {
                    deger=value;
               }
          }
     public string metod(string a)
     {
          return “Burak Selim SENYURT”;
     }
     int yas=27;
     string dogum=”istanbul”;
     }
} |
ikinci sınıfımızın kodları;
|
using System;
using System.Reflection;
namespace ReflectionSample3
{
     class Class1
     {
          static void Main(string[] args)
          {
               Type tipimiz=Type.GetType(“ReflectionSample3.OrnekSinif”);
               MemberInfo[] tipUyeleri=tipimiz.GetMembers();
               for(int i=0;i<TIPUYELERI.LENGTH;++I)
               {
                    Console.WriteLine(“Uye adi:”+tipUyeleri[i].Name.ToString()+” |Uye Tipi:”+tipUyeleri[i].MemberType.ToString());
               }
          }
     }
} |
Şimdi uygulamamızı çalıştıralım.

Åžekil 3. Kendi yazdığımı sınıf üyelerinede bakabiliriz.Â
Peki kendi sınıfımıza ait bilgileri edinmenin bize ne gibi bir faydası olabilir. İşte ÅŸimdi tam diÅŸimize gore bir örnek yazacağız. ÖrneÄŸimizde, bir tablodaki verileri bir sınıf içersinden tanımladığımız özelliklere alacağız. Bu uygulamamız sayesinde sadece tek satırlık bir kod ile, herhangibir kontrolü veriler ile doldurabileceÄŸiz. Bu uygulamada esas olarak, veriler veritabanındaki tablodan alınıcak ve oluÅŸturduÄŸumuz bir koleksiyon sınıfından bir diziye aktarılacak. OluÅŸturulan bu koleksiyon dizisi, bir DataGrid kontrolü ile iliÅŸkilendirilecek. Teknik olarak kodumuzda, Reflection uzayının PropertyInfo sınıfını kullanarak, oluÅŸturduÄŸumuz sınıfa ait özellikler ile tablodaki alanları karşılaÅŸtıracak ve uygun iseler bu özelliklere tabloda karşılık gelen alanlar içindeki deÄŸerleri aktaracağız. Dilerseniz kodumuz yazmaya baÅŸlayalım.Â
|
using System;
using System.Reflection;
using System.Data;
using System.Data.SqlClient;
namespace ReflectDoldur
{
     public class Kitap
     {
          private string kitapAdi;
          private string yayimci;
          /* Özelliklerimizin adlarinin tablmuzdan alacagimiz alan adlari ile ayni olmasina dikkat edelim.*/
          public string Adi
          {
               get
               {
                    return kitapAdi;
               }
              set
              {
                   kitapAdi=value;
              }
         }
         public string BasimEvi
         {
              get
              {
                   return yayimci;
              }
              set
              {
                   yayimci=value;
              }
         }
         /* Yapici metodumuz parametre olarak geçirilen bir DataRow degiskenine sahip. Bu degisken ile o anki satiri aliyoruz.*/
         public Kitap(System.Data.DataRow dr)
         {
              PropertyInfo[] propInfos=this.GetType().GetProperties(); /* this ile bu sinifi temsil ediyoruz. Bu sinifin tipini alip bu tipe ait özellikleri elde ediyor ve bunlar bir PropertyInfo sinifi tipinden diziye aktariyoruz.*/
              /* Döngümüz ile tüm özellikleri geziyoruz. Eger metodumuza parametre olarak geçirilen dataRow degiskenimiz, bu özelligin adinda bir alan içeriyorsa, bu özellige ait SetValue metodunu kullanarak özelligimize, iligili tablo alaninin degerini aktariyoruz.*/
              for(int i=0;i<PROPINFOS.LENGTH;++I)
              {
                   if(propInfos[i].CanWrite) /* Burada özelligimizin bir Set bloguna sahip olup olmadigina bakiliyor. Yani özelligimizen yazilabilir olup olmadigina. Bunu saglayan özelligimiz CanWrite. Eger özellik yazilabilir ise (yada baska bir deyisle readonly degil ise) true degerini döndürür.*/
                   {
                        try
                        {
                             if(dr[propInfos[i].Name]!=null) /* dataRow degiskeninde, özelligimin adindaki alanin degerine bakiliyor. Null deger degil ise SetValue ile alanin degeri özelligimize yazdiriliyor. */
                             {
                                  propInfos[i].SetValue(this,dr[propInfos[i].Name],null);
                             }
                             else
                             {
                                  propInfos[i].SetValue(this,null,null);
                             }
                        }
                        catch
                        {
                             propInfos[i].SetValue(this,null,null);
                        }
                   }
              }
         }
    }
     /* KitapKoleksiyonu sinifimiz bir koleksiyon olucak ve tablomuzdan alacagimiz iki alana ait verileri Kitap isimli nesnelerde saklanmasini sagliyacak. Bu nedenle, bir CollectionBase sinifindan türetildi. Böylece sinifimiz içinde indeksleyiciler kullanabilecegiz.*/
         public class KitapKoleksiyonu:System.Collections.CollectionBase
         {
              public KitapKoleksiyonu()
              {
                   SqlConnection conFriends=new SqlConnection(“data source=localhost;initial catalog=Friends;integrated security=sspi”);
                   SqlDataAdapter da=new SqlDataAdapter(“Select Adi,BasimEvi From Kitaplar”,conFriends);
                   DataTable dtKitap=new DataTable();
                   da.Fill(dtKitap);
        Â
                   foreach(DataRow drow in dtKitap.Rows)
                   {
                        this.InnerList.Add(new Kitap(drow));
                   }
              }
              public virtual void Add(Kitap _kitap)
              {
                   this.List.Add(_kitap);
              }
        Â
              public virtual Kitap this[int Index]
              {
                   get
                   {
                        return (Kitap)this.List[Index];
                   }
              }
         }
} |
Ve iÅŸte formumuzda kullandığımız tek satırlık kod;Â
|
private void btnDoldur_Click(object sender, System.EventArgs e)
{
     dataGrid1.DataSource = new ReflectDoldur.KitapKoleksiyonu();
} |
Åžimdi uygulamamızı çalıştıralım ve bakalım.Â

Åžekil 4. Programın Çalışmasının SonucuÂ
Görüldüğü gibi tablomuzdaki iki Alana ait veriler yazdığımız KitapKoleksiyonu sınıfı yardımıyla, her biri Kitap tipinde bir nesne alan koleksyionumuza eklenmiÅŸ ve bu sonuçlarda dataGrid kontrolümüze baÄŸlanmıştır. Siz bu örneÄŸi dahada iyi bir ÅŸekilde geliÅŸtirebilirisiniz. Umuyorumki bu örnekte yapmak istediÄŸimizi anlamışsınızdır. Yansıma tekniÄŸini bu kod içinde kısa bir yerde kullandık. Sınıfın özelliklerinin isminin, tablodaki alanların ismi ile aynı olup olmadığını ve aynı iseler yazılabilir olup olmadıklarını öğrenmekte kullandık. Â
Yorumlar
Yorum Yok
Yorumunuzu Ekleyin
Yorum eklemek için giris yapmalısınız.