|
|
|
Reflection(Yansıma) ile Tiplerin Sırrı Ortaya Çıkıyor |
|
| Gönderiliyor lütfen bekleyin... |
|
|
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
{
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
{
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
{
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
{
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
{
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.
Değerli
Okurlarım. Geldik bir makalemizin daha sonuna. Hepinize mutlu günler
dilerim.
Makale:
Reflection(Yansıma) ile Tiplerin Sırrı Ortaya Çıkıyor C#, Visual C# ve .NET Burak Selim Şenyurt
|
|
MAY 27
2006 |
Elinize sağlık, reflection olayini cok net bir sekilde anlatmissiniz. |
|
|
Sayfalar :
|
|
|
|
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|
|