Jump to content

Wpf | Reflection Nedir ?


wmismail

Recommended Posts

Başlık olarak ?Reflection? yazdıktan sonra ardına sayfalarca açıklama ve örnek konulabilir. Hatta bu konuda ayrı bir kitap bile yazılabilir. Reflection?ın çok farklı kullanımlar var. Özetleyerek hızlı bir şekilde tanımlamak istersek aslında Reflection bize hakkında bilgi sahibi olmadığınız programatik nesnelerle ilgili çalışma zamanında (run-time) bilgi alabilmemize olanak tanıyan bir metottur. Peki böyle bir şeye neden ihtiyacımız olsun? En basit örnek gerçek zamanlı olarak uygulamalara farklı DLL dosyalarının bağlandığı durumları gösterebiliriz. Böyle bir durumda kaynak konumdaki sınıflar veya metotlar ile ilgili herhangi bir bilgi bulunmaz. Söz konusu bu bilgilerin program çalışırken elde edilerek kullanılması gerekir. Gelin ilk olarak Reflection?ın yapısını ve sistemini tanımak adına tek bir uygulama içerisinde nasıl kullanılabileceğimize göz atalım. Örnek uygulamamızda aşağıdaki şekli ile tanımlanmış bir Urun sınıfı kullanacağız.

[VB]

Public Class Urun

Private PAdi As String

Public Property Adi() As String

Get

Return PAdi

End Get

Set(ByVal value As String)

PAdi = value

End Set

End Property

Sub New()

End Sub

Sub New(ByVal adi As String)

Me.Adi = adi

End Sub

Function Uyari() As String

Return "Ürünün adı: " & Me.Adi

End Function

End Class

[C#]

public class Urun

{

private string PAdi;

public string Adi

{

get { return PAdi; }

set { PAdi = value; }

}

public Urun()

{

}

public Urun(string adi)

{

this.Adi = adi;

}

public string Uyari()

{

return "Ürünün adı: " + this.Adi;

}

}

Uygulamamız içerisinde iki adet düğme yer alacak ve kullanacağımız Windows penceresinde global olarak tanımlanmış bir de Object tipinde değişkenimiz bulunacak.

[VB]

Dim BirUrun As Object

[C#]

object BirUrun;

Uygulama içerisindeki düğmelerden birine basıldığında global BirUrun değişkenimiz yeni bir Urun değişkenine dönüştürülecek.

[VB]

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

BirUrun = New Urun

End Sub

[C#]

private void button1_Click_1(object sender, EventArgs e)

{

BirUrun = new Urun();

}

Programımız içerisinde diğer düğmeye basıldığında BirUrun adındaki değişkenimizin Adi özelliğini değiştirerek Uyari adındaki metodunu kullanmak istiyoruz. Fakat Visual Studio içerisinde maalesef ki BirUrun adındaki değişkenle beraber Urun tipine ait Intellisense desteği gelmeyecektir. Aslında bu durumun haklı bir nedeni var. İkinci düğmeye basıldığında BirUrun adındaki değişkenin tipininin Object mi yoksa Urun mü olacağı belli değil. İşte tam da istediğimiz ortamı yaratmış olduk. Kullanacağımız nesnenin tipi belirsiz ve biz ona ait bazı özellikleri kullanmak istiyoruz. Bu durumda ilk olarak ikinci düğmeye basıldığında gerçekten BirUrun değişkeninin tipi Urun mü yoksa değil mi sorusunu kontrol etmemiz lazım.

[VB]

If TypeOf (BirUrun) Is Urun Then

End If

[C#]

if ((BirUrun) is Urun)

{

}

Buraya kadar her şey çok kolay. Bundan sonra eğer IF kontrollerimize olumlu sonuç dönüyorsa ilk olarak gidip nesnenin Adi özelliğini bulmamız ve ona bir değer aktarmamız gerekiyor.

[VB]

BirUrun.GetType.GetProperty("Adi").SetValue(BirUrun, "Daron", Nothing)

[C#]

BirUrun.GetType().GetProperty("Adi").SetValue(BirUrun, "Daron", null);

Yukarıdaki kod ile elimizdeki nesnenin tipini bilmeden onun Adi adındaki özelliğini (property) yakalayarak değerini Daron olarak değiştiriyoruz. Kodumuzu detaylı olarak adım adım bakacak olursak ilk aşamada nesnenin tipini GetType ile alıyoruz. Sonrasında ise tipini yakaladığımız nesnenin GetProperty ile Adi adındaki özelliğini alarak SetValue ile söz konusu özelliğin değerini değiştiriyoruz. SetValue metodu toplam üç parametre alıyor; bunlardan ilki değer değişikliği yapılacak nesnenin kendisi, ikincisi yeni atanacak olan değer, üçüncüsü ise eğer değiştirilecek olan özellik (property) indeksli ise söz konusu indeks değeri. Bizim örneğimizde indeksli bir özellik olmadığı için bu parametreyi boş geçiyoruz.

Değer atamamızı tamamladığımıza göre bu sefer de sıra geldi BirUrun değişkenimize ait Uyari metodunu çalıştırmaya. Metodumuz bize bir String döndürecek biz de onu doğrudan bir mesaj kutusu ile kullanıcıya göstereceğiz.

[VB]

BirUrun.GetType.InvokeMember("Uyari", Reflection.BindingFlags.InvokeMethod, Nothing, BirUrun, Nothing)

[C#]

BirUrun.GetType().InvokeMember("Uyari", System.Reflection.BindingFlags.InvokeMethod, null, BirUrun, null).ToString();

Reflection kullanarak türü bilinmeyen bir nesnenin bir metodunu çalıştırmak için InvokeMember metodundan faydalanmamız gerekiyor. InvokeMember aslında çok geniş kullanımı olan bir metod, biz şimdilik sadece bir çeşit kullanımına değineceğiz. Örneğimizde InvokeMember bir metod çalıştıracağı için ilk parametresinde çalıştırılacak olan metodun adını ikincisinde BindingFlags.InvokeMethod ile bir Metod çalıştırılacağını belirtiyoruz. Üçüncü parametre bizim şimdilik kullanım alanımız dışında kalan Binding?lerle ilgili, aynı şekilde beşinci parametre de boş bırakılarak geçilecek. Dördüncü parametrede ise hedef nesnemiz olan BirUrun değişkenimizi atayacağız. Böylece metodumuzu da çalıştırmış olduk.

Dinamik DLL Kullanımı

Kabaca Reflection?ın nasıl kullanılabildiğine dair bir örnek yaptıktan sonra artık sıra geldi harici bir DLL dosyasının çalışma anında programımıza ekleyerek içerisindeki yapıları kullanmaya. Bu çeşit bir işlevselliği özellikle gerçek zamanlı DLL derlemesi ile birleştirdiğinizde çok farklı bir dünyaya kapı açmış olacaksınız. Hedef olarak kullanacağımız DLL dosyasını aşağıdaki kodlardan yaratacağız.

[VB]

Public Class Deneme

Function Metin() As String

Return "Çalışıyor"

End Function

End Class

[C#]

public class Deneme

{

string Metin()

{

return "Çalışıyor";

}

Yarattığımız DLL dosyasını uygulamamız ile aynı konuma yerleştirdikten sonra aşağıdaki kod ile DLL?imizi kullanmaya başlayabiliyoruz.

[VB]

Dim BirAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom("ornek2.dll")

[C#]

System.Reflection.Assembly BirAssembly = System.Reflection.Assembly.LoadFrom("ornek2.dll");

Artık yukarıda tanımladığımız Assembly üzerinden Reflection kullanarak ilerleyebiliriz. İlk olarak Deneme adında sınıfımızdan bir instance almamız gerekecek. Bunun için Deneme tipini bulmamız lazım.

[VB / C#]

BirAssembly.GetModule("Ornek2.dll").GetType("Deneme")

Assembly üzerinden modülümüzü yakalıyor sonra da Deneme adındaki tipinizi buluyoruz. Tabi tipi bulmak yeterli değil, söz konusu tipte bir değişken yaratmamız gerekiyor. Activator sınıfını kullanarak bu tip üzerinden bir instance yaratarak Sinif adında bir değişkene aktaracağız.

[VB]

Dim Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"))

[C#]

object Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"));

Yarattığımız sınıfın maalesef özellikleri otomatik olarak gelmeyecek. O nedenle Metin adındaki metodumuzu da elle bularak çalıştırmak zorundayız.

[VB]

BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, Nothing)

[C#]

BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, null)

Yine Assembly üzerinden yola çıkarak bu sefer daha da ileri gidiyoruz. Deneme sınıfımızı bulduktan sonra içerisinde Metin adındaki metodumuzu buluyor ve doğrudan Invoke ile söz konusu metodu çalıştırıyoruz. Invoke metodu bizden iki parametre istiyor; bunlardan ilki ana sınıfın kendisi. Bir önceki adımda yakaladığımız sınıfı buraya parametre olarak aktarıyoruz. Diğeri ise bizim kullanmayacağımız Binding parametresi.

Metin metodumuz çalıştırıldığında geriye bir String değişkeni döndürüyor. Bu değişkeni de bir mesaj kutusu ile kullanıcıya göstermek istersek uygulamamızın tam kodunun aşağıdaki şekilde sonlanması gerekiyor.

[VB]

Public Class Form2

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim BirAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom("ornek2.dll")

Dim Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"))

MsgBox(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, Nothing))

End Sub

End Class

[C#]

namespace CSReflection

{

public partial class Form2 : Form

{

public Form2()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{

System.Reflection.Assembly BirAssembly = System.Reflection.Assembly.LoadFrom("ornek2.dll");

object Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"));

MessageBox.Show(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, null).ToString());

}

}

}

Böylece harici bir DLL dosyasını yükleyerek istediğimiz metodu dinamik olarak kullanabildik. Farklı durumlarda isterseniz bir DLL içerisinde tüm metod, sınıf ve özelliklerin listelerini alabilir hatta bunları LINQ sorguları ile tarayabilirsiniz.

[VB]

Dim Metodlar = From Gelenler In BirAssembly.GetModule("Ornek2.dll").GetTypes Where Gelenler.GetMethod("Metin") IsNot Nothing

[C#]

var Metodlar = from Gelenler in BirAssembly.GetModule("Ornek2.dll").GetTypes() where Gelenler.GetMethod("Metin") != null select Gelenler;

Örneğin yukarıdaki LINQ sorgumuz ile harici DLL dosyası içerisinde Metin adında metodu olan tüm sınıfların bir listesini alıyoruz.

Daron Yöndem

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...