wmismail Posted June 12, 2009 Share Posted June 12, 2009 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 More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.