18 Haziran 2018 Pazartesi

SQL CROSS APPLY Nedir?


Genelde CROSS APPLY olayını açıklayıcı anlatan Türkçe kaynak pek yok. Ben dilim döndüğünce anlatmaya çalışacağım.

Bir örnekle açıklamak iyi olacak: Diyelimki yöneticiniz sizden her personelin ofise son 2 giriş tarihlerini istedi diyelim. Bu durumda muhtemelen ilk aklınıza gelen, ne var ki her personel için SELECT TOP 2 * FROM XXX ORDER BY GIRIS_TARIHI DESC gibi bir sorgu yazar veririm dersiniz di mi? Bu örneği kafanızda iyice canlandırın. Bu sonucu nasıl çekebilirsiniz? Her personelin son 2 giriş tarihi... Eğer bizden istenen tek bir personelin son 2 giriş tarihi olsaydı işimiz gayet kolaydı. Araya bir WHERE koşulu koyup PERSONEL_ID = 123 vb olanı getir derdiniz ama yöneticiniz tüm personel listesini istiyor. CROSS APPLY olmadan mutlaka herkesin bir çözümü olacaktır ama hiçbir çözüm CROSS APPLY kadar verimli olmayacaktır. Ayrıca CROSS APPLY bu işi oldukça pratik ve hızlı çözüyor.

Basit düşünelim, 2 tane tablomuz olsun: PERSONEL ve PERSONEL_GIRIS diye 2 tane tablomuz olsun. PERSONEL tablosunda personel bilgileri, ID, Adı Soyadı gibi, PERSONEL_GIRIS tablosunda da bu personellerin giriş tarihleri tutuluyor olsun. Her bir personel için n tane giriş. Log tablosu gibi düşünelim bunu. Personellerin giriş logu tutulan bir tablo gibi düşünelim.

PERSONEL tablomuzda aşağıdaki gibi veriler olsun:





PERSONEL_GIRIS tablomuz da aşağıdaki gibi olsun:




Bu durumda her bir personelin son 2 giriş tarihi aşağıdaki sorguyla kolayca bulunabilir:



Yukardaki sorguya dikkat ederseniz; CROSS APPLY için yazılan kısımda WHERE PG.PERSONEL_ID = PERSONEL.ID eşleştirmesi yaptık. CROSS APPLY içindeki tablo ile dışardaki tablo PERSONEL_ID ile joinleniyor. Böylece doğru personel eşleşmesi yapılmış oluyor. Aynı ifadede CROSS APPLY yerine INNER JOIN olsaydı içerde TOP 2 çekmek isteyen ifadeyle böyle bir eşleşmeye izin vermeyecekti. CORSS APPLY ile INNER JOIN arasındaki temel fark burda.  Ayrıca LOG_TBL kullanımına dikkat ediniz.

Eğer ki son 2 giriş değil de son 1 giriş istenseydi, TOP 2 yerine TOP 1 diyecektik. Aradaki farkı görüp daha da anlaşılması açısından aşağıdaki sonucu da yazıyorum:


Görüleceği üzere sadece son girişler getirildi. Çoğu zaman CROSS APPLY sonucunu döndüren TABLE cinsinden function da yazılır. Bunun da yukardaki örneklerden hiçbir farkı yok, sadece CROSS APPLY içine yazılan sorgu bir function'a taşınmış olur o kadar. Bu örnekleri çoğaltabiliriz.

Umarım faydalı olabilmişimdir...




Paylaş:

7 Mart 2018 Çarşamba

C# Using Disposable Kullanımı


usingin bir kullanım şeklini biliyorsunuz namespace dahil ederken kullanılır. Bu yazıda ise Disposable ile ilgili kullanımını anlatacağım.

Bildiğiniz üzere C# kendi içinde bir garbage collection mekanizmasına sahiptir. Garbage collection da bildiğiniz üzere, en kaba tabirle çöp toplama makinesi gibidir. Siz bir değişken tanımladığınızda, ister bir değer atayın, ister bir referans atayın derleyici bunun için bellekte bir yer ayırır ve o değişkenle işiniz bitince eğer onu yok etmezseniz daha sonra derleyici, belli bir kurala göre bu bellekte kalan artıkları bahsettiğimiz çöp toplama makinesi gibi çalışan garbage collection mekanizması ile temizler. Fakat bazen çok yoğun çalışan programlarda bir nedenle bu çöp toplama mekanizması geç kalabilir ve dolayısıyla belleğin şişmesine ve performansın düşmesine sebebiyet verebilir. Bu durumlarda kendi çöpümüzü kendimiz toplamız en güzel yoldur. İşte tam bu aşamada using kullanımı devreye girer. using kullandığımız zaman ilgili blokta işimiz bittiği anda, bellek temizleme mekanizması otomatikmen çalışacak ve belleğin şişmesi ve performansın yavaşlaması durumu böylece ortadan kalkacaktır. Peki using bunu nasıl yerine getirir? Öncelikle using ile kullanılacak bir nesne System.IDisposable arabiriminden türemiş olmalıdır. Böylelikle kullanılan blokta, bloktan çıkıldığı anda otomatikmen Dispose() metodu çağrılacak ve temizleme işi başlayacaktır. Böylece bu işi derleyiciye bırakmamış oluruz.


class UseUsing { static void Main() { StreamReader sr = new StreamReader("deneme.txt"); using (sr){ //sr nesnesini kullan //...... } //veya using (StreamReader sr2 = new StreamReader ("deneme.txt")){ //sr2 nesnesini kullan //....... } } }



Yukardaki örnekte StreamReader sınıfı IDisposable arabirimini uyguladığından bloktan çıkıldığı anda Dispose() metodu arka planda çalışacak ve sr ve sr2 nesneleri yok edilecek ve sizin ekstra bişey yapmanıza gerek kalmayacaktır.


Kısaca using ifadesi Disposable yöntemler kullanmamıza olanak tanır.

Faydalı olması dileğiyle...

İyi kodlamalar dilerim..


Paylaş:

28 Şubat 2018 Çarşamba

C# readonly ve const ifadeleri

readonly anahtar sözcüğü


Birçok yerde readonly ifadesini görmüşsünüzdür. readonly olarak tanımlanan bir değişken yalnızca okunmak üzere tanımlanır ve yalnızca 2 şekilde değer ataması yapılabilir.

  1. İlk tanımlandığında değer ataması yapılarak
  2. Bir constructor içinde değer ataması yapılarak
Yukardaki 2 durum hariç readonly değişkenine değer ataması yapılamaz.

Bu durum, aslında sadece bir yapılandırıcı tarafından değer ataması yapılması gerektiği durumlarda kullanışlıdır. Böylece daha sonra değer değiştirmesi önlenmiş olur. Kullanım alanı oldukça fazladır.

Aşağıdaki örneği inceleyelim:


class DenemeClass { readonly double x = 30; public DenemeClass(int _x) { x = _x; //İlk değer ataması yapıldı x = x * 5; //Burda değeri değiştiriliyor. Doğru ifade çünkü constructor içindeyiz. } public DenemeClass(double _x) { x = _x; } public void Show() { Console.WriteLine(x); } static void Main() { DenemeClass dc = new DenemeClass(10); dc.Show(); DenemeClass dc2 = new DenemeClass(10.2); dc2.Show(); dc2.x = 10.3;//HATA!! Burada "A readonly field cannot be assigned to
(except in a constructor or a variable initializer)" hatası alacaksınız.
Console.Read(); } }





Yukardaki örnekte dc2.x = 10.3; ataması yapıldığında program kızacaktır. Çünkü bir readonly değişken, hata açıklamasında yazdığı üzere sadece ilk değer atamasında ya da bir constructor'da set edilebilir.

const anahtar sözcüğü

Yukarda readonly ifadesini açıkladık. const da aslında readonly'e benzer özellikler gösterir. Aralarındaki fark, const ifadesi yalnızca ilk değer atamasında değer verilip daha sonra program boyunca tekrar değiştirilemeyecektir. Ayrıca ilk değer ataması zorunludur.

const int a; //HATA!! Değer ataması yapılmalıdır const int a = 10; //Doğru ifade. . . . a = 20; //HATA!! const bir değişken daha sonra değiştirilemez.

readonly ile const arasındaki farkı da bu şekilde açıklamış olduk.

Bir sonraki yazıda görüşmek üzere...

İyi kodlamalar dilerim..


Paylaş:

14 Şubat 2018 Çarşamba

C# Dynamic Tipler


C# bilindiği üzere sıkı tip denetimli bir dildir. Bu şu demek oluyor: Eğer bir tip derleme sırasında atandığı bir tip ile uyuşmuyorsa derleme başarısız olacak (hata verecek) demektir. Bazen derleme zamanında da değişken tipli tanımlamalara ihtiyaç olabilir. C# 4.0 bu esnekliği sağlamak için yeni bir tip eklemiştir: dynamic tipi. dynamic tipi tabiri caizse kılıktan kılığa girebilir, bukalemun gibi renk değiştirebilir :) dynamic tipi bütün tiplere dönüştürülebilir. Eee C#1.0'la gelen object tipi de bize bu esnekliği sağlıyordu ne gerek vardı derseniz onu da birazdan anlatacağım.

Aşağıdaki örnekle başlayalım:

class DynamicTypes { static void Main() { dynamic i; dynamic s; i = 10; s = "Bu bir string'tir"; Console.WriteLine("i'nin tipi: " + i.GetType()); Console.WriteLine("i'nin değeri: " + i); //i'ye int tipiymiş gibi davranalım. i = i * 10; Console.WriteLine("i'nin yeni değeri: " + i); Console.WriteLine("str'nin tipi: " + s.GetType()); Console.WriteLine("str'nin değeri: " + s); //s'ye string tipiymiş gibi davranalım. s = s.ToUpper(); Console.WriteLine("s'nin yeni değeri: " + s); i = "i'nin tipi değişti";//Bu atamayla i'nin tipi otomatik olarak değişti Console.WriteLine("i'nin değeri: " + i); Console.WriteLine("i'nin yeni tipi: " + i.GetType()); } }

Bu ekranın çıktısı aşağıdaki gibi olacaktır:

i'nin tipi: System.Int32
i'nin değeri: 10
i'nin yeni değeri: 100

str'nin tipi: System.String
str'nin değeri: Bu bir string'tir
s'nin yeni değeri: BU BİR STRİNG'TİR

i'nin değeri: i'nin tipi değişti
i'nin yeni tipi: System.String

Bu programı biraz yakından inceleyelim:

Öncelikle; dynamic i; diye bir değişken tanımladık. i'ye 10 değerini atadık. Derleyici bunun tipini otomatik olarak int olarak algıladı (int olduğunu i.GetType() ile yazdırınca gördük). Çünkü 10 int tipindedir. Aynı şey dynamic s için de geçerli. Atanan değer karakter katarı olduğundan otomatik olarak string tip algılaması yapıldı. Fakat şu noktaya özellikle dikkat edelim: ilerleyen satırlarda int tipinde olan i değişkenine string bir değer ataması yapılıyor. Derleyici bunu derlemekle birlikte, üstelik çalışma zamanında da hata vermedi. i'nin bundan sonraki tipi string oldu.

dynamic tipi, tip uyumsuzluğu derleme sırasında anlaşılamaz. Ancak çalışma zamanında tip uyumsuzluğu ortaya çıkarsa exception fırlatır. Örneğin aşağıdaki kod derleme zamanında hata almaz ama çalışma zamanında tip uyumsuzluğu hatası fırlatır.

dynamic s; s = "karakter katarı"; s = s * 2; //Çalışma zamanı hatası!! string ile int çarpılamaz!!

Önce dynamic tip string tipine dönüşüyor. Sonra 2 ile çarpılmaya çalışıyor. string ile int haliyle çarpılamaz ve hata fırlatır.

Buraya kadar dynamic tipin ne olduğunu az çok anladık. Şimdi gelelim dynamic ile object arasındaki farklara..

dynamic ile object Tipleri Arasındaki Fark


dynamic ile object arasındaki en temel fark, derleme zamanındaki tip uyumsuzluğu kontrolüdür. Bildiğiniz üzere object tipini kullanabilmemiz için unboxing (kutudan çıkarma) yapmamız gerekiyor. Yani bir tip object olarak tanımlanmışsa, karşı tarafta bunun tipinin ne olacağını belirtmeliyiz.

Console.WriteLine(obj.GetType());//int yazar obj = obj + 1; //Derleme hatası!!! obj'nin tipini belirtmeliyiz obj = (int)obj + 1; //Şimdi çalıştı...

Fakat dynamic tipi için böyle bir işleme gerek yok. dynamic tipler derleme sırasında hata almazken, object tipler için ise unboxing yapmalı, tipini açıkça belirtmeliyiz. Kısaca dynamic tipler bizi derleme hataları zahmetinden kurtarmaktadır. Fakat dynamic tipler her zaman güvenli bir program sunmayabilirler. Dikkatli kullanılmadığında çalışma zamanı hatalarına yol açabilirler. Bundan dynamic tipleri kullanmaktan kaçınmalıyız anlamı çıkarılmamalıdır. Tam tersine dynamic tip kullanımı bazen oldukça elverişli ve gerekli olabilmektedir.

var Anahtar Sözcüğü


dynamic tipleri anlatıp var tipinden bahsetmemek olmazdı. var tipi de tıpkı dynamic tipler gibi herhangi bir tipte bir değişken değeri olabilir. Temel düzeyde javascript biliyorsanız javascriptteki var tanımlayıcısıyla çok benzerlik gösterir. Peki aralarında ne gibi farklar var?

var ile dynamic Tipler Arasındaki Farklar


Yukarda var tipinin de değişken tiplerde değer alabildiğini ifade etmiştik. dynamic tiplerden bazı farklarla ayrılır. dynamic tipler null olabiliyorken var tipleri mutlaka bir başlangıç değerine sahip olmalıdır. Ayrıca ilk atanan tip neyse program sonlanana kadar aynı tipte olmak zorundadır. Bunu bir örnekle açıklayalım.

dynamic x = null; x = 10; //x int tipinde x = x + 10; //x yine int tipinde x = "string değer"; //Geçerli ifade: x burda string tipine dönüştü. var y = null; //Hata!! null değer ataması yapılamaz! var y = 10; //y değişkeni int tipinde bir ilk değer almıştır. y = "string değer"; //Hata!! y yukarda ilk değeri int almıştı. string değer ataması yapılamaz

Buraya kadar object, dynamic ve var gibi dinamik tiplerden bahsetttik. Aşağıda bu üç dinamik tip arasındaki farkları tablo halinde bulabilirsiniz.

object, dynamic ve var Arasındaki Farklar


objectdynamicvar
object .NET Framework içindeki herhangi bir tipte bir değişken olabilir.Herhangi bir tipte bir değişken olabilirHerhangi bir tipte bir değişken olabilir fakat bir başlangıç değerine sahip olmalıdır.

Derleyici nesne hakkında bilgi sahibidir.

Derleyici nesne hakkında bilgi sahibi değildir. Intellisense ile "." dan sonra herhangi bir seçenek çıkmaz.

Derleyici nesne hakkında bilgi sahibidir. nesne hangi tipteyse ona göre intellisense ile bilgi edinmek mümkündür.

Bir metoda parametre olarak gönderilebilir veya bir metodun dönüş tipi olabilir.Bir metoda parametre olarak gönderilebilir veya bir metodun dönüş tipi olabilir.Bir metoda parametre olarak geçilemez ya da bir metodun dönüş tipi olamaz.

Tip ataması yapıldığında boxing - unboxing yapılmak zorundadır.Tip dönüşümü (boxing - unboxing) gerekmemektedir.Tip dönüşümü (boxing - unboxing) gerekmemektedir.
unboxing sırasında tip dönüştürülemezse hata fırlatır.

Tip dönüşümü hataları derleme zamanında anlaşılmaz ancak çalışma zamanında tip dönüştürülemezse hata fırlatır.

Tip dönüşümü derleme sırasında gerçekleşir. Hata varsa derleme yapılmaz.

Genel hatlarıyla dynamic tipleri anlatmaya çalıştım.

Umarım faydalı olabilmişimdir...

Hepinize iyi kodlamalar dilerim :)


Paylaş:

13 Şubat 2018 Salı

Visual Basic 6.0 Türkçe Karakter Sorunu (ı-ý, İ-Ý, ş-þ, Ş-Þ, ğ-ð, Ğ-Ð)


Hala Visual Basic 6.0 kullanan var mı bilmiyorum ama bir vesileyle bu aralar kullanmak zorunda kaldım :) Modern programlama dilleri ve IDE'lerini kullandıktan sonra bu tarz eski teknolojilere alışmak bir hayli zaman alıyor.

Neyse gelelim konumuza.. Karşılaştığım bu karakter sorununu belki başkaları da karşılaşmıştır diye belki bir faydam olur diye paylaşmak istedim.

Efsane Visual Basic 6.0 kodunu açtım birşeyler değiştirmem gerekiyor fakat kod sayfasında özellikle ı, ğ, ş harflerinde sorun olduğunu gördüm. Comment bile yazmak istesem abuk sabuk harfler çıkıyor. Region ayarlarından dil ayarlarını kaldırıp tekrar yükledim, klavye ayarlarını kaldırıp tekrar yükledim, server ı restart ettim ama yine düzelmemişti. Çıkan harfler ise aşağıdaki gibiydi.

ı  yerine  ý
İ  yerine  Ý
ş  yerine  þ
Ş  yerine  Þ
ğ  yerine  ð
Ğ  yerine  Ð

Eğer sizde de harfler yukardaki gibi çıkıyorsa o zaman doğru yerdesiniz. Çözümünü ise biraz zor bulmakla birlikte çok kolay olduğunu gördüm. Aşağıdaki yolu izleyip kodun font familysini aşağıdaki gibi değiştiriyorsunuz ve sorun düzeliyor. Açıkçası benim çok zor aklıma geldi font kaynaklı olabileceği.

Visual Basic 6.0 > Tools > Options > Text Editor > Normal Text > Courier New TUR 

Kolay gelsin..


Paylaş:

11 Şubat 2018 Pazar

C# Kısmi Tipler ve Kısmi Metotlar (Partial Class, Partial Methods)


Merhaba,

Bu yazıda, kısmi tiplerden bahsedeceğim.

Büyük boyutlu programlarda bazen aynı amaçlar için kullanılan çok uzun olabilecek cs dosyalarını bölmek mümkündür. Böylece takibi daha da kolaylaştırmış oluruz. 100'lerce satır arasında kaybolmaktansa bazen birbiriyle bağlantılı 3-5 metot için ayrı cs dosyaları oluşturmamız mümkün olabilir.

Kısmi tipleri belirtmek için partial anahtar sözcüğünü kullanacağız.

Öncelikle 3 ayrı dosyayı ayrı ayrı cs dosyası olarak kaydedelim.


--Bunu PartialClassX.cs olarak kaydedin
partial class PartialClassXY { public int X { get; set; } }


--Bunu PartialClassY.cs olarak kaydedin
partial class PartialClassXY { public int Y { get; set; } 
}

--Bunu PartialClassXY.cs olarak kaydedin
using System; partial class PartialClassXY { public PartialClassXY(int x, int y) { this.X = x; this.Y = y; } static void Main() { PartialClassXY xy = new PartialClassXY(10, 20); Console.WriteLine("X: " + xy.X + " Y: " + xy.Y); } 
}

Programı çalıştırdığınızda aşağıdaki çıktıyı alacaksınız:

X: 10 Y: 20

Örnekte görüldüğü gibi, aynı namespace içinde olmak kaydıyla herhangi bir yerde partial class anahtar sözcüğü ile ortak bir sınıf oluşturmamız mümkündür. Dikkat edildiğinde PartialClassXY.cs dosyasında this.X ve this.Y elemanlarına (PartialClassXY.cs'de tanımlı olmadığı halde) sınıfın elemanlarıymış gibi erişebiliyoruz. Sonuç olarak partial class sayesinde PartialClassX.cs, PartialClassY.cs ve PartialClassXY.cs dosyalarını tek bir çatı altında toplamış olduk.

Kısmi tipler tanımlanabildiği gibi Kısmi Metotlar da tanımlanabilir. Aşağıdaki örnek kısmi metotlara örnektir.
using System; partial class PartialClassXY { public int X { get; set; } partial void Show() { Console.WriteLine("X: " + X + " Y: " + Y); } } partial class PartialClassXY { public int Y { get; set; } public void ShowXY() { Show(); } } partial class PartialClassXY { public PartialClassXY(int x, int y) { this.X = x; this.Y = y; } partial void Show(); } class Test { static void Main() { PartialClassXY xy = new PartialClassXY(10, 20); xy.ShowXY(); Console.Read(); } 
}

Kısmi metodun tanım şekline dikkat ediniz: partial void Show(); 

Diğer parçada ise bu metodun içi doldurulmuştur.
partial void Show() { Console.WriteLine("X: " + X + " Y: " + Y); 
}

Artık bu metot diğer parçalarda çağrılırsa çalışacaktır. Diğer parçada ise bu metot çağrılmıştır.
public void ShowXY() { Show(); 
}

Diyelim ki Show() metodunu derlemeye dahil etmezsek ShowXY() boş çalışacaktır. Kısmi metodun asıl faydası da burda yatmaktadır.

Umarım faydalı olabilmişimdir.

Bir sonraki makalede görüşünceye dek hoşçakalın...


Paylaş:

8 Şubat 2018 Perşembe

C# ?? Operatörü


Bir önceki makalemizde boş bırakılabilen tiplerden bahsetmiştik. O yazıdan hatırlanacağı üzere ? operatörü boş bırakılabilen (nullable types) tipler deklare etmemizi sağlıyordu. ?? operatörü de boş bırakılabilen tiplerle ilgilidir.

Aşağıdaki if else yapısını bilmeyen yoktur:

bool b = true; string str = b ? "true" : "false"; //Burada str = "true" değerini alacaktır

?? operatörü de aslında yukardaki ifadeyi nullable tipler için gerçekler. Daha açık ifadeyle; nullable bir tip nullable olmayan bir tipe atanmak istendiğinde hata fırlatmanın önüne geçmek için bu ifade kullanılabilir.

Aşağıdaki örneği inceleyelim:

using System; class NullableTypesDemo { static void Main() { int? x = null; int y; y = x ?? 0; Console.WriteLine("x boş iken y'nin değeri: " + y); x = 10; y = x ?? 0; Console.WriteLine("x'e atama yapıldıktan sonra y'nin değeri: " + y); } }

Bu kodun çıktısı aşağıdaki gibi olacaktır:

x boş iken y'nin değeri: 0
x'e atama yapıldıktan sonra y'nin değeri: 10

Görüldüğü üzere ?? operatörü aslında nullable bir tipin null değer içerip içermediğini, eğer null ise default bir değer atayabilmeyi sağlar. Değer mevcut ise nullable değişkenin değeri, değer mevcut değilse ?? operatörünün sağındaki değer (default) ataması yapılır.

Umarım faydalı olabilmişimdir..

Bir sonraki makalede görüşmek üzere, sağlıcaklakalın..


Paylaş:

7 Şubat 2018 Çarşamba

C# Boş Bırakılabilen Tipler (Nullable Types)


Merhaba,

Bu yazıda sizlere C#'ta boş bırakılabilen tiplerden (Nullable Types) bahsedeceğim.

Program yazarken içeriği boş olabilecek değişkenlere sıklıkla ihtiyaç duyacaksınız. Örneğin; bir okul programında öğrenci bilgilerini kaydettiğimizi düşünelim. Ad, soyad, numara, adres, boy, kilo gibi alanlarımız olsun. Bir öğrencinin her zaman bütün bilgileri dolu olmayabilir. Örneğin boy, kilo gibi bilgileri o anda verilmemiş olabilir. Dolayısıyla bu alanlar boş bırakılacaktır. Daha önceleri boş bırakılamayan tipler sebebiyle bunu yönetmek zahmetli bir işti ama C# 2.0 ile birlikte bu konu zarif bir biçimde çözümlenmiştir. Boş bırakılabilen (Nullable Types) sayesinde bu sorun kolayca yönetilebilmektedir.

Normalde aşağıdaki kod parçası derlenmeyecektir

int i = null; //Hata!! i boş olamaz. (Boş bırakılamayan tip) bool b = null; //Hata!! b boş olamaz. (Boş bırakılamayan tip)

Fakat aşağıda bu tipleri nasıl boş bırakabileceğimizi göreceğiz.

Boş bırakılabilen tipler System.Nullable < T > nesnesidir. T bir değer tipi olmak zorundadır. İki şekilde deklarasyon olabilir

System.Nullable< int > i = null; System.Nullable< bool > b = null veya int? i = null; //Boş bırakılabilen tip bool? b = null; //Boş bırakılabilen tip

Genellikle ikinci deklarasyon daha çok tercih edilir. Program şimdi derlenecektir.

Boş bırakılabilen tiplerin boş bırakılabilmesi özelliği dışında bütün özellikleri boş bırakılamayan tiplerle aynıdır. Boş bırakılabilen bir tipin değer atanmış olup olmadığını iki şekilde anlayabiliriz. Birincisi null kontrolü yapılarak, ikincisi HasValue özelliğini kullanarak. HasValue kontrolü daha yaygın kullanılmakla birlikte daha şık bir kullanımdır.

Alın size bir örnek:

using System; class NullableTypesDemo { static void Main() { int? i = null; if (i.HasValue) Console.WriteLine("i bir değere sahip: " + i.Value); else Console.WriteLine("i boş"); i = 10; if (i.HasValue) Console.WriteLine("i bir değere sahip: " + i.Value); else Console.WriteLine("i boş"); } }

Bu programın çıktısı aşağıdaki gibi olacaktır:

i boş 
i bir değere sahip: 10

Bir nullable değişken ile normal değer değişkeni toplandığında değer yine null olacaktır.

Aşağıda bunu gösteren bir örnek vardır:

using System; class NullableTypesDemo { static void Main() { int? a = null; int? sonuc = null; int b = 10;//Dikkat!! Burası nullable değil sonuc = a + b; if (sonuc.HasValue) Console.WriteLine("Sonuc: " + sonuc.Value); else Console.WriteLine("Değer boş!"); a = 100; sonuc = a + b; if (sonuc.HasValue) Console.WriteLine("Sonuc: " + sonuc.Value); else Console.WriteLine("Değer boş!"); Console.Read(); } }

Bu programın çıktısı aşağıdaki gibi olacaktır:

Değer boş!
Sonuc: 110

Görüldüğü gibi değeri null olan bir nullable değişken ile değeri null olmayan int tipinde bir değişken toplandığında değer yine null olmaktadır.

Boş bırakılabilen tipler yalnızca değer tiplerine uygulanabilir.

Aşağıdaki ifade geçerli değildir:

class A {} static void Main(){ A? a = null; //Hata!! A nesnesi nullable olamaz }

Umarım faydalı olabilmişimdir..

Bir sonraki makalede görüşmek üzere..




Paylaş:

18 Ocak 2018 Perşembe

C# Attributes (Nitelikler) - Yazı Serisi - 3


Merhaba,

Daha önceki yazı serilerimizde Runtime Type Identification ve Reflection'dan bahsetmiştik. Bu yazıda da aslında Reflection'un bir parçası olan "Nitelikler"i ele alacağız.

Nitelikler de aslında Reflection'un bir parçasıdır ve çalışma zamanında uygulanan nesneye özellik katarlar. Başka bir deyişle nitelikler bir sınıf, yapı, metot ve benzerleri için bir metadata tanımlarlar. Bir class yapısı düşünün, bir özelliği olsun ve bu özelliği istediğimiz zaman kullanabilelim. İlk bakıldığında bu iş için properties'ler uygun gibi görünebilir ama bu tek bir özellik için o kadar da şık bir kullanım olmayacaktır. Hem kullanıcı her nesne oluşturduğunda bu özelliğe atama yapmayı unutabilir hem de reflection yapısı için uygun bir tercih olmayacaktır. İşte her bir yapının sahip olabileceği bu özellikler nitelikler (attributes) ile çok kullanışlı hale gelmektedir.

Bir nitelik, System.Attribute'den türemiş olmalıdır. Yani siz bir nitelik tanımlamak isterseniz, bu niteliğinizi her koşulda System.Attribute'den türetmelisiniz. Bir nitelik sınıfı tanımlarken de AttributeUsage adlı nitelik yazılmalıdır. AttributeUsage bu niteliğin hangi öğelere uygulanabileceğini tanımlar.

Aşağıda, bulunduğu öğeyi tarif eden özellikte basit bir nitelik örneği mevcuttur:

using System; [AttributeUsage(AttributeTargets.All)] public class MyAttribute : Attribute { public string AttributeParameter1 {get; set; } string strExplain; public MyAttribute(string _strExplain) { strExplain = _strExplain; AttributeParameter1 = "My attribute parameter value"; } public string Explain { get { return strExplain; } } } [MyAttribute("My attribute explain", AttributeParameter1="Dışardan parametre")] public class DenemeAttribute { //...... } public class UseAttribute { static void Main(string[] args) { Type t = typeof(DenemeAttribute); Console.WriteLine(t.Name + "'in nitelikleri"); object[] attributes = t.GetCustomAttributes(false); foreach (object o in attributes) { Console.WriteLine(o); } //Niteliği okuyalım Type tAttribute = typeof(MyAttribute); MyAttribute ma = (MyAttribute)Attribute.GetCustomAttribute(t, tAttribute); Console.WriteLine(ma.Explain);//Konumsal parametre Console.WriteLine(ma.AttributeParameter1);//Adlandırılmış parametre Console.Read(); } }

Bu programın çıktısı aşağıdaki gibidir:

DenemeAttribute'in nitelikleri
MyAttribute
My attribute explain
Dışardan parametre

Bu programda neler yaptık inceleyelim:

Öncelikle; MyAttribute adında bir attribute oluşturduk.

[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute

"AttributeTargets.All" ifadesi attributenin uygulandığı classın bütün elemanlarına uygulanacağı anlamına gelir. Bunu sadece istediğiniz yapılara (class, constructor, method.. vs) uygulanacak şekilde uyarlayabilirsiniz. Attribute tanımının son ekinin "Attribute" olması zorunlu olmamakla birlikte tavsiye edilir ama bu attributeyi bir yapıya tahsis ederken "Attribute" son ekini vermesek de olur. Yani aşağıdaki iki tanım da geçerlidir:

[MyAttribute("My attribute explain")] public class DenemeAttribute { //...... } veya [My("My attribute explain")] public class DenemeAttribute { //...... }

iki tanım da geçerlidir

Attribute'u tanımlarken constructor ile konumlanmış parametreye dikkat ediniz, sadece get; olarak verilmiştir. Buna konumsal parametre denir ve attribute verirken parantezi takiben ilk verilen parametre grubudur. Sonra AttributeParameter1 propertiesi tanımlandı. Buna da adlandırılmış parametre denir ve bir yapıya attribute verirken bu parametre dışardan set edilebilir.

Nitelikler hakkında genel hatlarıyla bir bilgi vermiş olduk.

Faydalı olması dileğiyle..





Paylaş:

C# Reflection (Yansıma) - Yazı Serisi - 2


Merhaba, bir önceki yazımızda Runtime Type Identification - RTTI konusunu ele almıştık. Bu yazımızda da C#'ın en güçlü özelliklerinden biri olan Reflection konusunu inceleyeceğiz.

Reflection Nedir?


Reflection, bir programın runtime sırasında dinamik olarak tip oluşturması, yüklemesi ve kullanması işlemidir. Reflection'a neden ihtiyaç var derseniz; daha büyük projeler yaptıkça göreceksiniz ki, daha dinamik, daha esnek yapılara ihtiyaç duyacaksınız. Bu ihtiyaçlardan biri de Reflection'dur. Reflection, çalışma zamanında (runtime) bir tip hakkında bilgi edinebilmemizi ve bu tipin özelliklerine göre davranabilmemizi sağlar. Bu özellik C#'ın çok güçlü bir özelliğidir. Yansıma denmesinin sebebi, reflection ile bir tipin aynadaki yansıması benzetmesidir. Burda ayna görevi gören yapı Type nesnesidir. Örneklerle konuyu detaylandırmaya çalışacağız.

Reflection'un en önemli yapılarından birisi System.Type nesnesidir. Yukarda bahsettiğimiz bir tip hakkında bilgi edinme işlemi System.Type nesnesi sayesinde yapılır. Type nesnesi System.Reflection.MemberInfo adında bir abstract sınıftan türemiştir.

MemberInfo önemli olduğundan, sahip olduğu özellikleri aşağıda belirtelim:

Type DeclaringType: Üyenin tanımlandığı class veya interfacein tipini elde eder
MemberTypes MemberType: Üyenin türünü elde eder. Örneğin; özellik mi, metot mu gibi bilgileri elde eder.
int MetaDataToken: Metadata iliştirilmiş bir değeri elde eder.
string Name: Üyenin adını elde eder.
Type ReflectedType: Reflection yapılan nesnenin tipini elde eder.

Bunların yanında MemberInfo'nun nitelikler (attributes) ile ilgili iki tane de abstract metodu vardır: GetCustomAttributes() ve IsDefined(). İlki, adından da anlaşılacağı üzere ilgili nesneye iliştirilmiş attributelerin listesini getirir, diğeri de ilgili nesne için tanımlanmış attribute var mı yok mu diye kontrol eder. Nitelikler konusunu bir sonraki yazıda ele alacağız.

Bunun gibi daha birçok metot ve özellik vardır. Hepsini burda ele almak konuyu haddinden fazla uzatacaktır. Hepsi de ismiyle müsemma anlaşılabilir cinstendir. Örneğin; reflectionda kullanılmış bir GetParameters() metodu görürseniz bilin ki bu metodun parametrelerini getirecektir.

Şimdi gelelim bu öğelerin kullanımına.. Bir örnekle başlayalım:

using System; using System.Reflection; class MyClass { int x; int y; public MyClass(int i, int j) { this.y = j; this.x = i; } public int Sum() { return x + y; } public bool IsBetween(int i) { if (x &lt; i &amp;&amp; i &lt; y) return true; return false; } public string DummyMethod(int a, int b) { return "Bu da 2 parametreli metot"; } public void Show() { Console.WriteLine("x değeri: " + x + " y değeri: " + y); } } class ReflectionTest { static void Main() { Type t = typeof(MyClass); //Burda MyClass'ın görüntüsü alınır MethodInfo[] mi = t.GetMethods();//Burda MyClass'ın metot listesi getirilir Console.WriteLine("Nesnenin adı: " + t.Name); Console.WriteLine("Nesnenin desteklediği metotlar:"); foreach (MethodInfo m in mi) { //Metot dönüş tipi ve adı ParameterInfo[] pi = m.GetParameters(); Console.WriteLine("Metot Adı: " + m.Name + "Dönüş tipi: " + m.ReturnType.Name); //Parametre varsa parametrelerini göster if (pi.Length &lt;= 0) Console.WriteLine("Parametre yok"); for (int i = 0; i &lt; pi.Length; i++) { Console.Write(i + 1 + ". parametre: Dönüş Değeri: " + pi[i].ParameterType.Name + " Adı: " + pi[i].Name + "\n"); } Console.WriteLine(); } Console.Read(); } }

Bu programın çıktısı aşağıdaki gibi olacaktır:

Nesnenin adı: MyClass
Nesnenin desteklediği metotlar:
Metot Adı: SumDönüş tipi: Int32
Parametre yok

Metot Adı: IsBetweenDönüş tipi: Boolean
1. parametre: Dönüş Değeri: Int32 Adı: i

Metot Adı: DummyMethodDönüş tipi: String
1. parametre: Dönüş Değeri: Int32 Adı: a
2. parametre: Dönüş Değeri: Int32 Adı: b

Metot Adı: ShowDönüş tipi: Void
Parametre yok

Metot Adı: ToStringDönüş tipi: String
Parametre yok

Metot Adı: EqualsDönüş tipi: Boolean
1. parametre: Dönüş Değeri: Object Adı: obj

Metot Adı: GetHashCodeDönüş tipi: Int32
Parametre yok

Metot Adı: GetTypeDönüş tipi: Type
Parametre yok
.........................

Bu örnekte neler yaptık inceleyelim: Öncelikle MyClass'ın görüntüsünü elde ettik. Bunu Type t = typeof(MyClass) ile yaptık. Artık t nesnesi MyClass'ın sahip olduğu özelliklere sahiptir. Ama bu new ile oluşturulan nesnelere benzemez. Bu işlem, reflectionda kullanılabilecek bir tip oluşturur. Zaten amacımız MyClass nesnesi oluşturmak olsaydı bunu şu şekilde yapardık: MyClass mc = new MyClass(); ama amacımız bu değil, amacımız runtime sırasında istediğimiz tipi elde etmek. Type ile MyClass'ın görüntüsünü elde ettikten sonra, sahip olduğu metotları listeledik (MethodInfo[] mi = t.GetMethods()). Daha sonra her bir metodun parametrelerini aldık (ParameterInfo[] pi = m.GetParameters()). Program adım adım incelenirse, gayet anlaşılır ve kolay niteliktedir.

Yukardaki örnekle ilgili son olarak, çıktıya dikkat ederseniz MyClass içinde tanımlanmayan ToString, Equals.. gibi metotlar gözükmekte. Bunun nedeni, bütün tiplerin kalıtım yoluyla object'ten türetilmiş olmasıdır.

GetMethods()'un başka bir kullanım şekli daha var:

MethodInfo[] GetMethods(BindingFlags bindingAttr).

BindingFlags enumerator tipindedir. En çok kullanılan tipler ise şunlardır:

DeclaredOnly: Yalnız belirtilen class tarafından tanımlanan metotları getirir. Kalıtım yoluyla aktarılan metotları getirmez.
NonPublic: nonpublic metotları getirir.
Public: public metotları getirir.
Static: static metotları getirir.

Bu kullanım şeklinde birden fazla tipi aynı anda kullanmamız mümkündür. Bu durumda aralarına "|" işaretini koymak gerekiyor. Bunun faydalarından biri de object'ten gelen metotların ya da kalıtım yoluyla gelen başka metotların listesini almamak içindir.

Yukardaki ilgili satırı aşağıdaki gibi değiştirin:

MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);

Çıktı aşağıdaki gibi olacaktır:

Nesnenin adı: MyClass
Nesnenin desteklediği metotlar:
Metot Adı: SumDönüş tipi: Int32
Parametre yok

Metot Adı: IsBetweenDönüş tipi: Boolean
1. parametre: Dönüş Değeri: Int32 Adı: i

Metot Adı: DummyMethodDönüş tipi: String
1. parametre: Dönüş Değeri: Int32 Adı: a
2. parametre: Dönüş Değeri: Int32 Adı: b

Metot Adı: ShowDönüş tipi: Void
Parametre yok
.........................

Görüldüğü üzere object metotları gelmemiş oldu.

Olay basit aslında. Type nesnesine MyClass'ın görüntüsünü alsın diye bir görev yükledik (Type t = typeof(MyClass)). Artık burdaki nesne MyClass'ın görüntüsünü elde edecektir ve sahip olduğu tüm metotları elde edebilecek ve kullanabilecektir. Programcıkta görüldüğü üzere, t nesnesi MyClass'ın bütün özelliklerini kendine yükledi.

Şimdiiiii gelelim bu yazıyı merakla okuyanların daha da merak edeceği bir şeye: Metotları reflection ile çağırmak..

Metotları Reflection İle Çağırma


Yukardaki örneklerde bahsettiğimiz gibi Type ile bir tipin metotlarını elde ettikten sonra Invoke() ile bu metotları çağırabiliriz. Invoke()'nin prototipi aşağıdaki gibidir:

object Invoke(object nesne, object[] argümanlar)

Bunu bir örnekle inceleyelim: Örneğin uzunluğuna takılmayın, yukardaki koda birkaç satır daha ilave ettik. Kopuk olmasın diye ya da bunu uygulamak isteyen biri hepsini alıp kullanabilsin diye tekrar tekrar yazdım:

using System; using System.Reflection; class MyClass { int x; int y; public MyClass(int i, int j) { this.y = j; this.x = i; } public int Sum() { return x + y; } public bool IsBetween(int i) { if (x &lt; i &amp;&amp; i &lt; y) return true; return false; } public void Set(int a, int b) { Console.WriteLine("Set(int, int) metodu çağrıldı"); x = a; y = b; Show(); } public void Set(double a, double b) { Console.WriteLine("Set(double, double) metodu çağrıldı"); x = (int)a; y = (int)b; Show(); } public void Show() { Console.WriteLine("x değeri: " + x + " y değeri: " + y); } } class InvokeTest { static void Main() { Type t = typeof(MyClass); MyClass mc = new MyClass(10, 20); int res; Console.WriteLine(t.Name + " metotları Reflection ile çağrılıyor..."); Console.WriteLine("Örnek: MyClass mc = new MyClass(10, 20)"); Console.WriteLine(); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) { //Metodun parametrelerini alalım ParameterInfo[] pi = m.GetParameters(); if (m.Name.Equals("Set", StringComparison.Ordinal) &amp;&amp; pi[0].ParameterType == typeof(int)) { object[] args = new object[2]; args[0] = 3; args[1] = 4; m.Invoke(mc, args); } else if (m.Name.Equals("Set", StringComparison.Ordinal) &amp;&amp; pi[0].ParameterType == typeof(double)) { object[] args = new object[2]; args[0] = 6.2; args[1] = 9.7; m.Invoke(mc, args); } else if (m.Name.Equals("Sum", StringComparison.Ordinal)) { res = (int)m.Invoke(mc, null); Console.WriteLine("Sum metodu çağrıldı. Sonuç: " + res); } else if (m.Name.Equals("IsBetween", StringComparison.Ordinal)) { object[] args = new object[1]; args[0] = 13; bool isBetween = (bool)m.Invoke(mc, args); if (isBetween) Console.WriteLine("IsBetween metodu çağrıldı. 13 sayısı 10 ile 20 arasındadır"); } else if (m.Name.Equals("Show", StringComparison.Ordinal)) { m.Invoke(mc, null); } } Console.Read(); } }

Bu programın çıktısı aşağıdaki gibi olacaktır:

MyClass metotları Reflection ile çağrılıyor...
Örnek: MyClass mc = new MyClass(10, 20)

Sum metodu çağrıldı. Sonuç: 30
IsBetween metodu çağrıldı. 13 sayısı 10 ile 20 arasındadır
Set(int, int) metodu çağrıldı
x değeri: 3 y değeri: 4
Set(double, double) metodu çağrıldı
x değeri: 6 y değeri: 9
x değeri: 6 y değeri: 9

Görüldüğü üzere; Invoke() metodu ile çalışma sırasında dinamik olarak değer atamaları yaptık ve ardından bu metotları çağırdık. Burda dikkat etmeniz gereken bir nokta da, aşırı yüklenmiş Set metodunun ilgili versiyonunu (Set(int a, int b) ve Set(double a, double b)) bulmak için parametre tipi kontrolü yapılması gerektiği. İlgili kontroller aşağıdaki satırlarda gösterilmiştir:

if (m.Name.Equals("Set", StringComparison.Ordinal) &amp;&amp; pi[0].ParameterType == typeof(int)) if (m.Name.Equals("Set", StringComparison.Ordinal) &amp;&amp; pi[0].ParameterType == typeof(double))

Type ile Yapılandırıcıları (Constructor) Çağırmak


Yukardaki örneklerde reflection ile metotları nasıl elde edip nasıl kullanılacağını anlattık. Fakat bu örnekler metotları çağırmak dışında bir işe yaramamıştı. Çünkü zaten nesneyi biz yapılandırmıştık. Reflection'un esas gücü bir nesne runtime sırasında oluşturulduğunda (ilk yapılandırma) ortaya çıkar. Tabiki bunun için yapılandırıcıları da elde etmemiz gerekecektir. Bunun için, tahmin edeceğiniz üzere Type'ın GetConstructors() metodunu çağırmamız gerekiyor. İlgili constructor bulunduktan sonra, çalıştırmak için yine Invoke() metodunu kullanacağız. Constructoru çağırarak ilk değer atamaları yapıldıktan sonra ilgili metodu yine benzer yöntemle çağıracağız.

Aşağıdaki örneği inceleyelim:

using System; using System.Reflection; class MyClass2 { int x; int y; public MyClass2(int a, int b) { this.x = a; this.y = b; } public int Sum() { return x + y; } } class InvokeConstructorTest { static void Main() { Type t = typeof(MyClass2); int res; //Constructor bilgilerini al Console.WriteLine(t.Name + "'in yapılandırıcıları:"); ConstructorInfo[] ci = t.GetConstructors(); foreach (ConstructorInfo c in ci) { //Dönüş tipi ve adını gösterelim Console.Write(t.Name + "("); ParameterInfo[] pi = c.GetParameters(); for (int i = 0; i &lt; pi.Length; i++) { Console.Write(pi[i].ParameterType.Name + " " + pi[i].Name); if (i &lt; pi.Length - 1) Console.Write(", "); } Console.WriteLine(")"); } //Biz 2 parametreli yapılandırıcıyı arıyor olacağız int x;//bu değişkende, aradığımız constructorın indexi tutulacak for (x = 0; x &lt; ci.Length; x++) { ParameterInfo[] pi = ci[x].GetParameters(); if (pi.Length == 2) break; } //Buraya aranan constructor bulunmadığı durumda //programdan çık gibi kontroller eklenebilir //Şimdi de nesneyi yapılandıralım object[] constParams = new object[2]; constParams[0] = 10; constParams[1] = 20; object ob = ci[x].Invoke(constParams); Console.WriteLine("Nesne, constructor(10, 20) ile yapılandırıldı..."); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) { ParameterInfo[] pi = m.GetParameters(); if (m.Name.Equals("Sum", StringComparison.Ordinal)) { Console.WriteLine("Sum() metodu çağrılıyor..."); res = (int)m.Invoke(ob, null); Console.WriteLine("Sonuç bulundu: " + res); } } Console.Read(); } }

Bu programın çıktısı aşağıdaki gibi olacaktır:

MyClass2'in yapılandırıcıları:
MyClass2(Int32 a, Int32 b)
Nesne, constructor(10, 20) ile yapılandırıldı...
Sum() metodu çağrılıyor...
Sonuç bulundu: 30

Bu örneği incelersek; ilk önce yapılandırıcı listesini elde ettik. 2 parametreli yapılandırıcıyı bildiğimizden 2 parametreli olanı bulduk (daha karmaşık yapılandırılar için önceki örneklerde olduğu gibi parametre tipi kontrolü yapılarak ilgili yapılandırı bulunabilir). Sonra bu yapılandırıcıya runtime zamanında değer atadık ve nesneyi yapılandırdık. Sonra ilgili metodu da aynı yöntemle bularak, yapılandırıcı ile yapılandırdığımız nesnenin metodunu çağırdık.

Assembly'leri Reflection'da Kullanmak


Buraya kadar hep açık kodunu bildiğimiz yapılar için reflection kullandık. Fakat reflectionun tam gücü assembly'lerin kullanımında ortaya çıkmaktadır. Bildiğiniz üzere bir assembly, içerdiği classlar, yapılar, metotlar ve parametreler gibi birçok bilgiyi beraberinde taşır. Bu da reflection kullanımı için son derece uygundur. Bu şekilde dışardan eklenen bir assembly için sık sık tanımlama gereği duymadan reflection ile dinamik ve esnek olarak kullanabiliriz. Örneğin; bir sistemdeki tüm tipleri araştıran ve görsel olarak ortaya koyan bir "tip tarayıcısı" gibi bir programınızın olduğunu düşünelim. Bu noktada reflection kullanmak işinizi son derece kolaylaştıracaktır.

Assembly'lerin kullanımına bir örnek yapalım. Öncelikle birkaç classtan oluşan bir program yazıp derleyeceğiz. Sonra bu programın derlenmesi sonucu oluşan exe'yi runtime sırasında yükleyip kullanacağız.

Basit olması açısından bir proje oluşturup 3 tane class yerleştirip derleyelim. Derlendikten sonra dizinin altında bir exe oluşacaktır. Bu exe'nin adını belirtip ilgili tipleri elde ettikten sonra yine aynı yöntemlerle kullanacağız:

using System; using System.Reflection; public class MyClass { int x; int y; public MyClass(int a, int b) { this.x = a; this.y = b; } public int Sum() { return x + y; } } public class OtherClass { public string Show() { return "Bu da diğer class"; } } public class UseAssemblyReflection { static void Main() { int res; Assembly asm = Assembly.LoadFrom("ReflectionAssembly.exe"); Type[] types = asm.GetTypes(); Console.WriteLine("ReflectionAssembly.exe'deki tiplerin listesi"); foreach (Type temp in types) { Console.WriteLine(temp.Name); } Type t = types[0];//MyClass'ı alıyoruz Console.WriteLine("\nMyClass'ın Constructorları listeleniyor"); ConstructorInfo[] ci = t.GetConstructors(); foreach (ConstructorInfo c in ci) { //Dönüş tipi ve adını gösterelim Console.Write(t.Name + "("); ParameterInfo[] pi = c.GetParameters(); for (int i = 0; i &lt; pi.Length; i++) { Console.Write(pi[i].ParameterType.Name + " " + pi[i].Name); if (i &lt; pi.Length - 1) Console.Write(", "); } Console.WriteLine(")"); } //Biz 2 parametreli yapılandırıcıyı arıyor olacağız int x;//bu değişkende, aradığımız constructorın indexi tutulacak for (x = 0; x &lt; ci.Length; x++) { ParameterInfo[] pi = ci[x].GetParameters(); if (pi.Length == 2) break; } //Buraya aranan constructor bulunmadığı durumda //programdan çık gibi kontroller eklenebilir //Şimdi de nesneyi yapılandıralım object[] constParams = new object[2]; constParams[0] = 10; constParams[1] = 20; object ob = ci[x].Invoke(constParams); Console.WriteLine("\nNesne, constructor(10, 20) ile yapılandırıldı..."); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) { ParameterInfo[] pi = m.GetParameters(); if (m.Name.Equals("Sum", StringComparison.Ordinal)) { Console.WriteLine("Sum() metodu çağrılıyor..."); res = (int)m.Invoke(ob, null); Console.WriteLine("Sonuç bulundu: " + res); } } Console.Read(); } }

Bu programın çıktısı aşağıdaki gibi olacaktır:

ReflectionAssembly.exe'deki tiplerin listesi
MyClass
OtherClass
UseAssemblyReflection

MyClass'ın Constructorları listeleniyor
MyClass(Int32 a, Int32 b)

Nesne, constructor(10, 20) ile yapılandırıldı...
Sum() metodu çağrılıyor...
Sonuç bulundu: 30


Ben projemi oluştururken ReflectionAssembly adını vermiştim. Bu yüzden ilgili exe'yi belirtirken "ReflectionAssembly.exe" olarak belirttim. Assembly'nin yüklenme şekline dikkat ediniz:


Assembly asm = Assembly.LoadFrom("ReflectionAssembly.exe");

asm nesnesine ilgili exe'nin bilgileri yüklendikten sonra tipleri elde etmek için aşağıdaki satırı kullandık.

Type[] types = asm.GetTypes();

Bundan sonrası yine yukarda anlattığımız yöntemlerle aynı.

Not: Burda unutulmaması gerekir ki, yüklenmesi gereken assembly'nin türü illa ki exe olması gerekmez. Projenin türüne göre dll de olabilir. dll olması durumunda Add > Reference ile referans eklendikten sonra direk ilgili dll'in adı verilebilir (ObjectDeneme.dll gibi) ya da referans eklemeden direk path olarak da verilebilir (C:\users\......\ObjectDeneme.dll gibi)

Reflection hakkında bu kadar bilgi verdikten sonra diyeceksiniz ki, biz zaten özelliklerini bildiğimiz dll veya exe'leri kullandık. Zaten daha önce de belirtmiştik bir assembly beraberinde tiplerin özelliklerini de taşır. Dolayısıyla bu normal bir durumdur. Fakat hiç özelliklerini bilmediğiniz tiplerin de reflection ile özelliklerini açığa çıkarmanız mümkündür. Yukardaki kodları, hayal gücünüze bağlı olarak daha dinamik hale getirip aynı anda sistemdeki bütün tiplerin özelliklerini listeleyebilirsiniz.

Reflection konusunun sonuna geldik. Bir sonraki yazımızda Nitelikler konusunu ele alacağız.

Umarım faydalı olabilmişimdir... Hepinize iyi günler dilerim..


Paylaş:

Bu Blogda Ara