Reflection kütüphanesini kullanarak dinamik metot çağrısı yapabilmemiz mümkündür. Geri dönüş tipi void olan ve parametre almayan static bir metot yazalım ve dinamik olarak çağırmaya çalışalım.

class Program

    {

        static void Main(string[] args)

        {          

 

            Console.Write("Metot adı yazınız : ");

            string metotAdi = Console.ReadLine();

            MethodInfo mi = typeof(Program).GetMethod(metotAdi, BindingFlags.Static | BindingFlags.NonPublic);

            mi.Invoke(null, null);

        }

 

        static void DinamikMetot()

        {

            Console.WriteLine("Ben dinamik olarak çalıştırıldım.");

        }

     }

Programı çalıştıralım ve ekranda metodumuzun adını yazarak enter’a basalım.

image

image

Gördüğünüz gibi metot dinamik olarak çalıştırılmış durumda. Yaptığımız işlem çok basit bir reflection işlemidir aslında. Dinamik olarak Program tipinin metotlarını elde ediyoruz, metot ismi olarak ise çalışma anında kullanıcı tarafından girilen bilgiyi parametre olarak veriyoruz. BindingFlags enum’ı ile verilen parametreler ile de metodun static ve private olduğunu belirtiyoruz. Daha sonra da invoke ederek gerekli parametreleri gönderiyoruz.

Şimdi de DinamikTopla adında bir metot yazalım. Metodun geri dönüş tipi void olsun ve 2 adet integer tipinden parametre alarak toplamlarını ekrana yazdırsın.

class Program

    {

        static void Main(string[] args)

        {

            Console.Write("Metot adı yazınız : ");

            string metotAdi = Console.ReadLine();

           

            MethodInfo mi = typeof(Program).GetMethod(metotAdi, BindingFlags.Static | BindingFlags.NonPublic);

           

            Console.Write("Birinci parametre : ");

            int p1 = int.Parse(Console.ReadLine());

           

            Console.Write("İkinci parametre : ");

            int p2 = int.Parse(Console.ReadLine());

           

            mi.Invoke(null, new object[] { p1, p2 });

        }

 

        static void DinamikTopla(int a, int b)

        {

            Console.WriteLine("DinamikTopla metodu çalıştı! Toplam = {0}", a + b);

        }

     }

Programı çalıştıralım ve istenen değerleri ekranda vererek sonucu elde edelim.

image

image

image

image



Reflection, çalışma zamanında .NET assemblylerini, tiplerini ve tiplerin üyelerini dinamik olarak kullanma fırsatı veren yapıdır. Reflection namespace’i içerisinde bulunan tipler ile üyelere dinamik olarak erişme şansına sahibiz.  Basit bir console uygulaması üzerinden örnek uygulama yapalım.

Öncelikle bilgi alacağımız tipi elde etmemiz gerekmektedir. Bunu 3 farklı yol ile yapabilmemiz mümkündür. Elde ettiğimiz tipi “Type” tipinden bir değişkende tutarız. Adından da belli olduğu gibi Type, tipin tipini tutan bir tiptir Smile   bool tipine dinamik olarak erişerek içerisindeki üyelerin isimlerini öğrenmeye çalışalım.

using System.Reflection;

 

namespace ReflectionKavrami

{

    class Program

    {

        static void Main(string[] args)

        {

            Type tip = typeof(Boolean);

            //Type tip = new Boolean().GetType();

            //Type tip = Type.GetType("System.Boolean");

 

            MemberInfo[] tipUyeleri = tip.GetMembers();

 

            Console.WriteLine("{0} tipi içerisinde {1} adet üye mevcuttur.", tip.Name, tipUyeleri.Length);

 

            int i = 1;

            foreach (MemberInfo member in tipUyeleri)

            {

                Console.WriteLine("{0} - Üye adı : {1} , Üye tipi : {2}", i, member.Name, member.MemberType);

                i++;

            }

        }

    }

}

image

Üyeleri elde etmek için kullandığımız GetMembers metodu, System namespace’I altındaki Type sınıfı içerisinde yer alan non-static bir metottur. Geriye dönüş tipi olan MemberInfo ise System.Reflection namespace’i altında yer alan bir tiptir.

Tüm üyeleri elde etmek yerine, ilgili tipe ait metotları, alanları, property’leri, event’leri, yapıcı metotları da elde etme şansına sahibiz. Type sınıfı içerisinde bu işlemleri yapan ilgili metotlar mevcuttur. Geri dönüş tipleri de System.Reflection isim uzayı altında tanımlı tiplerdir.

Projemize System.Windows.Forms kütüphanesini referans edelim ve Button sınıfı hakkındaki bazı bilgileri ekrana yazdıralım.

class Program

    {

        static void Main(string[] args)

        {

            Type tip = new Button().GetType();

 

            Console.WriteLine("NameSpace : {0}", tip.Namespace);

            Console.WriteLine("FullName : {0}", tip.FullName);

            Console.WriteLine("Assembly : {0}", tip.Assembly.FullName);

            Console.WriteLine("BaseType : {0}", tip.BaseType);

            Console.WriteLine("is Class : {0}\n", tip.IsClass.ToString());

 

            Console.WriteLine("{0} tipi içerisinde tanımlı;", tip.Name);

            Console.WriteLine("\t{0} adet constructor metot,", tip.GetConstructors().Length);

            Console.WriteLine("\t{0} adet property,", tip.GetProperties().Length);

            Console.WriteLine("\t{0} adet metot,", tip.GetMethods().Length);

            Console.WriteLine("\t{0} adet event vardır", tip.GetEvents().Length);

        }

    }

image

Çalışma anında belirlenen bir tipin nesne örneğini oluşturmak isteyelim. Kullanıcıdan bir tip adı girmesini isteyelim ve bu tipten bir nesne örnekleyelim.

class Program

    {

        static void Main(string[] args)

        {           

            Console.WriteLine("Lütfen bir tip adı giriniz");

            string tipAdi = Console.ReadLine();

 

            Type tip = Type.GetType(tipAdi);

            object obj = Activator.CreateInstance(tip);

 

            Console.WriteLine(obj == null ? "Nesne oluşturulamadı." : "Nesne dinamik olarak örneklendi");

        }

    }

image

image

Son örneğimizde de .net framework içerisinde yer alan bir assembly’I elde edelim ve içerisindeki namespace’lere göre gruplama yapalım. Daha sonra da her bir namespace altındaki toplam tip sayısını ve bu tiplerin adlarını ekrana yazdıralım.

class Program

    {

        static void Main(string[] args)

        {

            Assembly assembly = Assembly.LoadFile(@"C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll");

 

            foreach (var group in assembly.GetTypes().GroupBy(t => t.Namespace))

            {

                Console.WriteLine("{0}({1})", group.Key, group.Count().ToString());

 

                Console.WriteLine("*****************************");

 

                foreach (Type tip in group)

                {

                    Console.WriteLine(tip.Name);

                }

                Console.WriteLine();

            }

        }

    }

image

Çalışma anında tipler hakkında nasıl bilgi alınacağından kısaca bahsetmiş olduk. Faydalı olması dileği ile…



Bazı noktalarda, işimizi kolaylaştıran stored procedure’leri uygulamalarımıza dahil etme ihtiaycı hissedebiliriz. SqlDataAdapter ile nasıl yapıldığını şuradan inceleyebilirsiniz. Şimdi de bu işlemi Entity Framework ile nasıl yapacağımızı inceleyeceğiz. Örnek uygulamamızda AdventureWorks veri tabanını kullanacağız.

SQL tarafında bir stored procedure oluşturarak örneğimize başlayalım. Yapacağı iş, bölgelerin adlarını ve toplam satış miktarlarını göstermek olsun.

CREATE PROC USERSP_BolgelereGoreSatis

AS  

      SELECT SST.Name[Bölge Adı], SUM(SOD.LineTotal) [Toplam Satış] FROM Sales.SalesOrderDetail SOD

      JOIN Sales.SalesOrderHeader SOH ON SOD.SalesOrderID=SOH.SalesOrderID

      JOIN Sales.SalesTerritory SST ON SST.TerritoryID=SOH.TerritoryID

      GROUP BY SST.Name

image

Bir windows form uygulaması açalım ve formumuza bir DataGridView kontrolü ile bir button ekleyelim. Amacımız, butona basıldığında grid içerisine procedure’den gelen sonuçları doldurmak olsun.

image

Procedure’ümüzü uygulamamıza dahil edebilmek için projemize sağ tuş tıklayarak, add new item >> ADO.NET Entity Data Model ekleyelim ve ilgili procedure’ü seçerek işlemi tamamlayalım. Modelin eklenmesi sırasındaki adımların detaylarını şuradan inceleyebilirsiniz.

image

Procedure’ü modelimize ekledikten sonra bir metot gibi kullanabilmemiz için “Function Import” seçeneğinden ilgili düzenlemeleri yapmamız gerekir. Burada, metodun ismini ve en önemlisi, geriye döndürdüğü tipi belirtme şansına sahibiz.

Modelimizi ekledikten sonra karşımıza çıkan edmx uzantılı pencerede boş bir yere sağ tuş tıklayarak Model Browser’ı seçelim.

image

Sağ tarafta açılan küçük pencerede, Stored Procedures altında, eklemiş olduğumuz procedure’ü bularak sağ tuş tıklayalım ve “Add function Import”u seçelim.

image

Karşımıza çıkan pencerede ilgili procedure’ün hangi isim ile metotlaştırılacağı ve geriye dönüş tipinin ne olacağı bilgileri yer almaktadır. Elde edeceğimiz sonuç kümesinde bölge isimleri ve toplam satış miktarları mevcut idi. Yani string ve decimal tipinde iki kolon elde edeceğiz. Ekranda görülen “Get Column Information” butonuna tıklayarak, visual studio’dan yardım alabilir, geriye dönen sonuç kümesinde hangi tiplerin mevcut olduğunu görebiliriz.

image

Normal şartlarda bu metodu karşılayacak bir tip tasarlamamız, içerisine de string ve decimal tipinde iki property eklememiz gerekir. Ancak Entity Framework bizim için bu tipi otomatik olarak oluşturmaktadır. “Create New Complex Type” butonuna tıklayalım ve bu tipin oluşmasını sağlayalım.

image

Ok butonuna bastıktan sonra USERSP_BolgelereGoreSatis_Result adında bir tip otomatik olarak oluşturulacak ve içerisine 2 adet property eklenecektir. Bunu da Model Browser penceresinde ve designer içerisinde görmemiz mümkündür.

image

image

Artık procedure kullanılmaya hazır hale geldi. Uygulamamız içerisinde “USERSP_BolgelereGoreSatis” isimli, parametre almayan ve geriye ObjectResult<USERSP_BolgelereGoreSatis> tipinden bir sonuç döndüren metodumuz mevcut. Şimdi de butona basıldığında procedure’ü çalıştırarak grid içerisinde sonuç kümesini görüntüleyelim.

namespace EntityFrameworkSPCagirmak

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            AdventureWorksEntities context = new AdventureWorksEntities();

            dataGridView1.DataSource = context.USERSP_BolgelereGoreSatis();

        }

    }

}

Alacağımız ekran çıktısı aşağıdaki gibi olacaktır.

image



Daha önceki makalemizde LINQ’in aslında, Enumarable adlı static bir sınıf içerisinde yer alan extension metotlardan oluştuğundan bahsetmiştik. Bugün ise kendi LINQ metotlarımızı nasıl yazacağımızı göreceğiz. Bu sayede uygulamalarımızda, amacımıza uygun olarak LINQ metotları tasarlayabiliriz. Daha anlaşılır olması adına konuya başlamadan önce, Extension Metot, foreach iterasyonu, yield operatörü, anonim metot, lambda operatörü ve Linq metotları gibi konular hakkında fikir sahibi olmamızın işimizi kolaylaştıracağını hatırlatmakta fayda var.

İlk olarak Urun adında bir sınıf yazacağız. Daha sonra da Dukkan adlı bir sınıfımız olacak ve bu sınıf arka tarafta bir Urun dizisi tutacak. İçerisinde iterasyon yapacağımız sınıf Dukkan sınıfı olacaktır.

Yazacağımız LINQ metotları içerisinde ihtiyaç dahilinde Urun nesnelerini karşılaştırma ihtiyacı hissedeceğimizden dolayı IComparable interface’ini implement etmemiz gerekecektir.

public class Urun : IComparable<Urun>

    {

        public int Id { get; set; }

        public string Ad { get; set; }

        public double Fiyat { get; set; }

 

        public Urun(int id, string ad, double fiyat)

        {

            Id = id;

            Ad = ad;

            Fiyat = fiyat;

        }

 

        public static bool operator >(Urun u1, Urun u2)

        {

            return u1.Fiyat > u2.Fiyat;

        }

        public static bool operator <(Urun u1, Urun u2)

        {

            return u1.Fiyat < u2.Fiyat;

        }

 

        public int CompareTo(Urun other)

        {

            if (this.Fiyat > other.Fiyat)

                return 1;

            if (this.Fiyat < other.Fiyat)

                return -1;

            else return 0;

        }

    }

Dukkan sınıfı içerisinde de iterasyon yapacağımız için, IEnumerable interface’ini impelement etmesi gerekmektedir.

public class Dukkan : IEnumerable<Urun>

    {

        Urun[] _urunSepeti;

 

        public Urun[] UrunSepeti

        {

            get { return _urunSepeti; }

            set { _urunSepeti = value; }

        }

 

        Urun[] UrunleriGetir()

        {

            return new Urun[]

            {

                new Urun(1,"Monitör",200),

                new Urun(2,"Klavye",80),

                new Urun(3,"Mouse",40),

                new Urun(4,"Laptop",1000),

                new Urun(5,"TV",650)

            };

        }

 

        public Dukkan()

        {

            UrunSepeti = UrunleriGetir();

        }

 

        public IEnumerator<Urun> GetEnumerator()

        {

            for (int i = 0; i < UrunSepeti.Length; i++)

                yield return UrunSepeti[i];

        }

 

        IEnumerator IEnumerable.GetEnumerator()

        {

            return this.GetEnumerator();

        }

    }

Where

Buraya kadarki kısım geçmişe dönük ufak bir hatırlatma oldu diyebiliriz. Şimdi LINQ metotlarımızı yazmaya başlayabiliriz. Bunun için static bir sınıf oluşturalım ve içerisine metotlarımızı ekleyelim. İlk olarak Filtrele adında bir metot yazalım, işlevi Where metodu ile aynı olsun.

public static class BizimEnumerable

    {

        public static IEnumerable<T> Filtrele<T>(this IEnumerable<T> source, Func<T, bool> predicate)

        {

            foreach (T obj in source)

            {

                if (predicate(obj))

                    yield return obj;

            }

        }

    }

Metodun aldığı parametreleri inceleyelim. this anahtar sözcüğü ile, metodun hangi tipler üzerinde çıkacağını belirtiyoruz. Generic IEnumerable interface’ini implement eden tüm sınıflar bu metodu kullanabilecekler. ikinci parametre ise T tipinden parametre alan ve geriye bool dönen bir delegedir. Bir metot parametre olarak bir delege alıyorsa, bunun anlamı, parametre olarak bir metot göndermektir. Ya bu imzaya uygun bir metot yazıp bu metodu parametre olarak göndeririz. Ya da metodu anonim olarak tanımlarız. Ancak her işlem için yeni bir metot tanımlamak yerine lambda operatörü ile ananim metot yazmak işimizi fazlası ile kolaylaştıracaktır. Metodun içerisinde ise kaynak üzerinde iterasyon yapılır ve kaynak içerisindeki her bir nesne , ikinci parametrede belirtmiş olduğumuz anonim metoda parametre olarak verilir. Metot geriye bool bir değer döndüğünden, filtereden geçen eleman yield operatörü ile geriye döndürülür.

Program sınıfı içerisinde Dukkan tipinden bir nesne örnekleyelim ve Filtrele metodunu kullanalım. Adı ‘M’ ile başlayan ürünleri filtreleyerek ekrana yazdıralım.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            foreach (Urun u in dukkan.Filtrele(u => u.Ad.ToLower().StartsWith("m")))

            {

                Console.WriteLine(u.Ad);

            }

        }

    }

image

Şimdi de Where metodunun aşırı yüklenmiş bir versiyonunu yazalım, parametre olarak Func<T,int,bool> alsın. Yazacağımız anonim metot T ve int tipinden 2 parametre alarak geriye bool döndürecek. int tipinden olan parametre index’i temsil etmektedir.

public static IEnumerable<T> Filtrele<T>(this IEnumerable<T> source, Func<T, int, bool> predicate)

        {

            int index = 0;

            foreach (T obj in source)

            {

                if (predicate(obj, index))

                    yield return obj;

                index++;

            }

        }

Program tarafında testimizi yapalım. Bir integer dizisi oluşturalım. Değeri, bulunduğu index’in 10 katından küçük olan olan sayıları filtreleyelim.

int[] sayilar = { 0, 30, 20 };

 

foreach (int sayi in sayilar.Filtrele((s, i) => s <= i * 10))

{

Console.WriteLine(sayi);

}

image

Select

Görüldüğü gibi Filtrele metodu, where metodunun yaptığı işi yaparak verilen koşula göre filtreleme işlemini gerçekleştirdi. Şimdi de Select metodunu kendimiz yazalım. Metodun adı Seç olsun.

public static class BizimEnumerable

    {        

        public static IEnumerable<TResult> Sec<T, TResult>(this IEnumerable<T> source, Func<T, TResult> predicate)

        {

            foreach (T obj in source)

                yield return predicate(obj);

        }

    }

predicate delegesinin işaret ettiği metot parametre olarak T alan ve geriye TResult döndüren bir metottur. Sec metodu içerisinde kaynakta itersyon yapılır ve elde edilen her bir nesne predicate delegesinin işaret ettiği metoda verilir ve elde edilen değer geriye döndürülür. Bir ürün nesnesine karşılık adının elde edilmesi durumunu ele alalım. Burada T parametresi bir Urun iken, TResult  parametresi de bir string olur. Bir ürünün fiyatına karşılık kdv ekli fiyatını elde etmek istersek de T tipi de TResult tipi de double olur.

class Program

    {

        static void Main(string[] args)

        {

            foreach (string ad in dukkan.Sec(u => u.Ad))

            {

                Console.WriteLine(ad);

            }

 

            foreach (double kdvDahilFiyat in dukkan.Sec(u => u.Fiyat * 1.18))

            {

                Console.WriteLine(kdvDahilFiyat);

            }

 

  }

     }

image

Take

Getir adında, Take metodunun işlevine sahip bir metot tasarlayalım. Parametre olarak integer bir değer alsın ve bu parametre değeri kadar elemanı elde etmemizi sağlasın.

public static IEnumerable<T> Getir<T>(this IEnumerable<T> source, int number)

        {

            int counter = 0;

            foreach (T obj in source)

            {

                counter++;

                yield return obj;

 

                if (counter == number)

                    break;

            }

        }

dukkan içerisindeki ilk 3 ürünün adını ekrana yazdıralım.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            foreach (Urun u in dukkan.Getir(3))

            {

                Console.WriteLine(u.Ad);

            }

                   }

        }

image

Count

Say adında, Count metodu ile aynı işleve sahip bir metot yazalım. Daha sonra da bu metodun bir aşırı yüklenmiş versiyonunu yazarak, içerisinde filtreleme yapılabilmesini sağlayalım.

public static class BizimEnumerable

    {       

        public static int Say<T>(this IEnumerable<T> source)

        {

            int toplam = 0;

            foreach (T obj in source)

            {

                toplam++;

            }

            return toplam;

        }

 

        public static int Say<T>(this IEnumerable<T> source, Func<T, bool> predicate)

        {

            int toplam = 0;

            foreach (T obj in source)

            {

                if (predicate(obj))

                {

                    toplam++;

                }

            }

            return toplam;

        }

    }

Yazmış olduğumuz metotları Program tarafında test edelim.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            Console.WriteLine("Eleman sayısı : {0}", dukkan.Say());

 

            Console.WriteLine("***********************************************");

 

            Console.WriteLine("Fiyatı 100 liradan az olan ürün sayısı: {0}", dukkan.Say(u => u.Fiyat < 100));

        }

    }

Ekran çıktısı aşağıdaki gibi olacaktır.

image

Sum

Topla adında bir metot yazalım ve uygun tiplere göre aşırı yüklenmiş versiyonlarını ekleyelim.

public static class BizimEnumerable

    {

        public static double Topla<T>(this IEnumerable<T> source, Func<T, double> predicate)

        {

            double toplam = 0;

            foreach (T obj in source)

            {

                toplam += predicate(obj);

            }

            return toplam;

        }

 

        public static double? Topla<T>(this IEnumerable<T> source, Func<T, double?> predicate)

        {

            double? toplam = 0;

            foreach (T obj in source)

            {

                toplam += predicate(obj);

            }

            return toplam;

        }

 

        public static int Topla<T>(this IEnumerable<T> source, Func<T, int> predicate)

        {

            int toplam = 0;

            foreach (T obj in source)

            {

                toplam += predicate(obj);

            }

            return toplam;

        }

 

        public static int? Topla<T>(this IEnumerable<T> source, Func<T, int?> predicate)

        {

            int? toplam = 0;

            foreach (T obj in source)

            {

                toplam += predicate(obj);

            }

            return toplam;

        }

    }

Dukkan sınıfı içerisindeki fiyatların toplamını alalım. Alanların tipi double olduğundan dolayı, ilk yazdığımız versiyonu kullanacağız. Diğer versiyonları kullanmayacağız. Sadece nasıl olduğunu görmemiz açısından ele almak istedim.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            Console.WriteLine("Kaynaktaki ürünlerin toplam fiyatı : {0}", dukkan.Topla(u => u.Fiyat));

 

        }

    }

image

Average

public static class BizimEnumerable

    {

        public static double Ortalama<T>(this IEnumerable<T> source, Func<T, int> predicate)

        {

            int toplam = 0;

 

            foreach (T obj in source)

            {

                toplam += predicate(obj);

            }

 

            return toplam / source.Say();

        }

 

        public static double Ortalama<T>(this IEnumerable<T> source, Func<T, double> predicate)

        {

            double toplam = 0;

 

            foreach (T obj in source)

            {

                toplam += predicate(obj);

            }

 

            return toplam / source.Say();

        }

    }

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            double sonuc3 = dukkan.Ortalama(u => u.Fiyat);

            Console.WriteLine("Kaynaktaki ürünlerin ortalam fiyatları : {0}", sonuc3);

 

        }

    }

image

All, Any

All metodu, kaynaktaki tüm elemanların koşulu sağlayıp sağlamadığına  bakar. Biri bile sağlamıyorsa false döner. Any metodu ise koşulu sağlayan en az bir nesne varsa true döner.

public static class BizimEnumerable

    {

        public static bool BizimAny<T>(this IEnumerable<T> source, Func<T, bool> predicate)

        {

            foreach (T obj in source)

            {

                if (predicate(obj))

                    return true;

            }

            return false;

        }

 

        public static bool BizimAll<T>(this IEnumerable<T> source, Func<T, bool> predicate)

        {

            foreach (T obj in source)

            {

                if (!predicate(obj))

                    return false;

            }

            return true;

        }

    }

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            bool sonuc = new int[] { 1, 2, 3, 4, 5, 6, 7 }.BizimAny(s => s % 2 == 1);

            Console.WriteLine(sonuc);

 

            Console.WriteLine("***********************************************");

 

            bool sonuc2 = new int[] { 1, 2, 3, 4, 5, 6 }.BizimAll(s => s < 10);

            Console.WriteLine(sonuc2);

 

        }

    }

image

ToArray

LINQ metotlarından geriye sorgulanabilir nesneler döndüğünden bahsetmiştik. İçerisinde iterasyon yapıldığında çalışan bu sorgu nesnelerini bir diziye almak için ToArray metodunu kullanırız. Şimdi de bu metodu kendimiz tasarlayalım.

public static T[] DiziyeDoldur<T>(this IEnumerable<T> source)

        {

            int index = 0;

            T[] dizi = new T[source.Say()];

 

            foreach (T obj in source)

            {

                dizi[index++] = obj;

                //index önce kullanılır, sonra değeri bir artırılır.

            }

 

            return dizi;

        }

Metodumuzu kullanarak dukkan içerisindeki ürünleri bir Urun dizisine dolduralım ve ilk ürünün adını ekrana yazdıralım.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            Urun[] urunler = dukkan.DiziyeDoldur();

            Console.WriteLine(urunler[0].Ad);

        }

    }

image

First, FirstOrDefault()

First metodu, kaynakta eleman bulamassa exception fırlatır. FirstOrDefault ise o tipin default değerini getirir. Şimdi bu metotları tasarlayalım. Ayrıca birer tane aşırı yüklenmiş versiyonlarını ekleyerek, metot içerisinde filtreleme yapılabilmesini sağlayalım.

public static T IlkiniGetir<T>(this IEnumerable<T> source)

        {

            foreach (T obj in source)

            {

                return obj;

            }

 

            throw new NullReferenceException();

        }

 

        public static T IlkiniGetir<T>(this IEnumerable<T> source, Func<T, bool> predicate)

        {

            foreach (T obj in source)

            {

                if (predicate(obj))

                {

                    return obj;

                }

            }

            throw new NullReferenceException();

        }

 

        public static T IlkiniYadaVarsayilaniGetir<T>(this IEnumerable<T> source) where T : new()

        {

            T defaultType = new T();

 

            foreach (T obj in source)

            {

                return obj;

            }

 

            return defaultType;

        }

 

        public static T IlkiniYadaVarsayilaniGetir<T>(this IEnumerable<T> source, Func<T, bool> predicate) where T : new()

        {

            T defaultType = new T();

 

            foreach (T obj in source)

            {

                if (predicate(obj))

                {

                    return obj;

                }

            }

 

            return defaultType;

        }

NOT: Bizim yazdığımız “İlkiniYadaVarsayilaniGetir” metodu null yerine o tipten örneklenmiş ve default değerlere sahip bir nesne dönmektedir.

Buradaki “IlkiniYadaVarsayilaniGetir” metodu Dukkan tipi üzerinde çıkmayacaktır. Çünkü T tipine, parametre almayan bir constructor bulundurma zorunluluğu getirdik. Burada T tipi Urun sınıfıdır, Urun sınıfı içerisinde de tek bir constructor metot vardır, o da 3 parametre alan versiyonudur. Dolayısı ile bu metodu dukkan sınıfı üzerinde kullanabilmemiz için Urun sınıfına aşağıdaki constructor metodu ekleyelim.

public Urun()

        {

 

        }

Şimdi metotlarımızı test edebiliriz.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan dukkan = new Dukkan();

 

            //Urun urn = dukkan.IlkiniGetir(u => u.Fiyat > 1000);

            //Fiyatı 1000'den büyük olan ürün olmadığı için exception alırız.

 

            Urun u1 = dukkan.Filtrele(u => u.Ad.StartsWith("M")).IlkiniGetir();

            Console.WriteLine(u1.Ad);

           

            Urun u2 = dukkan.IlkiniGetir(u => u.Fiyat == 1000);

            Console.WriteLine(u2.Ad);

 

            Urun u3 = dukkan.Filtrele(u => u.Fiyat < 100).IlkiniYadaVarsayilaniGetir();

            Console.WriteLine(u3.Ad);

           

            Urun u4 = dukkan.IlkiniYadaVarsayilaniGetir(u => u.Fiyat > 1000);

            if (u4.Ad == null)

                Console.WriteLine("Nesne elde edilemedi.");

        }

    }

image

Buraya kadar kendi LINQ metotlarımızı yazabilmemizin mümkün olduğunu gördük. İhtiyacımız olduğu durumlarda, amacımıza uygun bir LINQ metodu tasarlayabiliriz. Metot tasarımı yaparken yapılan olduğumuz kodlama sizlerin hayal dünyasına göre farklılık gösterebilir. Ben sadece küçük bir kısmını ele almaya çalıştım.

Faydalı olması dileği ile…