Yükleniyor...

C# Reflection ve Late Binding

C#’ta Reflection ve Late Binding kullanımını öğrenin. Runtime tip keşfi, dinamik çağrılar ve esnek yapıların örnekleri anlatılıyor.

C# dilinde Reflection, çalışma zamanında (runtime) tip bilgisine erişmeyi, türler üzerinde işlem yapmayı ve nesneleri dinamik olarak oluşturmayı sağlar. Late Binding (geç bağlama) ise derleme zamanında tipi bilinmeyen nesnelere çalışma anında erişimdir. Bu iki mekanizma sayesinde esnek, plugin tabanlı veya dinamik modüler sistemler geliştirilebilir.


Reflection Nedir?

Reflection, bir derleme (assembly) içindeki tiplerin (sınıf, metot, property, field vb.) çalışma zamanında incelenmesini ve kullanılmasını sağlayan güçlü bir mekanizmadır. Örneğin derleme dosyasındaki sınıfları, metotları, nitelikleri (attributes) veya değerlerini görebilirsiniz.


using System;
using System.Reflection;

class Ornek
{
    public int Sayı { get; set; }
    public void Yaz() => Console.WriteLine("Yaz() metodu çağrıldı.");
}

class Program
{
    static void Main()
    {
        Type tip = typeof(Ornek);
        Console.WriteLine($"Sınıf adı: {tip.Name}");

        // Özellikleri listeleme
        foreach (var prop in tip.GetProperties())
            Console.WriteLine($"Özellik: {prop.Name}");

        // Metotları listeleme
        foreach (var metot in tip.GetMethods())
            Console.WriteLine($"Metot: {metot.Name}");
    }
}

Bu örnekte Type nesnesi, sınıfın yapısına dair tüm bilgilere erişim sağlar. GetMethods(), GetProperties(), GetFields() gibi metotlarla detaylı inceleme yapılabilir.


Late Binding (Geç Bağlama) Nedir?

Late Binding, derleme zamanında tipi bilinmeyen bir sınıfın örneğini çalışma zamanında oluşturmak anlamına gelir. Reflection kullanılarak sınıf yüklenir, nesnesi oluşturulur ve metotları dinamik olarak çağrılabilir. Özellikle plugin sistemlerinde, harici DLL’lerin yüklenmesinde ve dinamik tip yönetiminde yaygın olarak kullanılır.


using System;
using System.Reflection;

class Selamlayici
{
    public void SelamVer(string isim)
    {
        Console.WriteLine($"Merhaba, {isim}!");
    }
}

class Program
{
    static void Main()
    {
        // Çalışma anında tip bilgisiyle nesne oluşturma
        Type tip = Type.GetType("Selamlayici");
        object nesne = Activator.CreateInstance(tip);

        // Metot çağırma (Late Binding)
        MethodInfo metot = tip.GetMethod("SelamVer");
        metot.Invoke(nesne, new object[] { "Ahmet" });
    }
}

Burada Selamlayici sınıfı, adı string olarak verilerek çalışma anında yüklendi. Derleme sırasında tipi bilinmediği için buna geç bağlama denir.


Assembly Üzerinden Dinamik Yükleme

Assembly.LoadFrom() veya Assembly.Load() metotları ile dış bir DLL yüklenip içindeki tipler keşfedilebilir. Bu yaklaşım plugin veya modüler mimariler için sıklıkla kullanılır.


using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // Harici DLL yükleme
        Assembly dll = Assembly.LoadFrom("MyLibrary.dll");

        // Tipleri listeleme
        foreach (var tip in dll.GetTypes())
            Console.WriteLine($"Tip: {tip.FullName}");

        // Tipten örnek oluşturma ve metot çağırma
        Type hedefTip = dll.GetType("MyLibrary.MathHelper");
        object nesne = Activator.CreateInstance(hedefTip);
        MethodInfo metot = hedefTip.GetMethod("Topla");

        object sonuc = metot.Invoke(nesne, new object[] { 3, 5 });
        Console.WriteLine($"Toplam sonucu: {sonuc}");
    }
}

Bu yöntemle harici kütüphaneler çalışma anında yüklenebilir, tipleri ve metotları dinamik olarak kullanılabilir.


Property ve Field Değerlerine Dinamik Erişim

Reflection sadece metot çağırmakla sınırlı değildir; aynı zamanda property ve field değerlerine de erişebilir, hatta değiştirebilirsiniz.


using System;
using System.Reflection;

class Araba
{
    public string Marka { get; set; } = "Ford";
    private int Hız = 120;
}

class Program
{
    static void Main()
    {
        var araba = new Araba();
        Type tip = araba.GetType();

        // Public property okuma
        var prop = tip.GetProperty("Marka");
        Console.WriteLine("Marka: " + prop.GetValue(araba));

        // Private field erişimi
        var field = tip.GetField("Hız", BindingFlags.NonPublic | BindingFlags.Instance);
        Console.WriteLine("Hız: " + field.GetValue(araba));

        // Değer değiştirme
        field.SetValue(araba, 200);
        Console.WriteLine("Yeni Hız: " + field.GetValue(araba));
    }
}

BindingFlags kullanarak public, private veya static üyeler üzerinde kontrol sağlayabilirsiniz.


Öznitelik (Attribute) Bilgilerine Erişim

Reflection sayesinde sınıf veya üyeler üzerine tanımlanan Attribute bilgilerine de erişilebilir. Bu özellik, metadata temelli işlem yapan kütüphanelerde (ör. ORM, serializer) sıklıkla kullanılır.


using System;

[AttributeUsage(AttributeTargets.Class)]
class BilgiAttribute : Attribute
{
    public string Aciklama { get; }
    public BilgiAttribute(string aciklama) => Aciklama = aciklama;
}

[Bilgi("Bu sınıf örnek amaçlıdır.")]
class Ornek { }

class Program
{
    static void Main()
    {
        Type tip = typeof(Ornek);
        var attr = (BilgiAttribute)Attribute.GetCustomAttribute(tip, typeof(BilgiAttribute));

        Console.WriteLine($"Açıklama: {attr.Aciklama}");
    }
}

Bu mekanizma, sınıflara metadata ekleyip çalışma zamanında bu bilgileri okumaya olanak tanır.


Performans ve Güvenlik Dikkatleri


Örnek: Plugin Sistemi

Reflection genellikle plugin veya modüler sistem oluşturmak için kullanılır. Aşağıdaki örnek, bir DLL içinde IPlugin arayüzünü uygulayan sınıfları bulup dinamik olarak yükler.


using System;
using System.Linq;
using System.Reflection;

public interface IPlugin
{
    string Ad { get; }
    void Calistir();
}

class Program
{
    static void Main()
    {
        Assembly dll = Assembly.LoadFrom("EklentiPaketi.dll");
        var pluginTipleri = dll.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface);

        foreach (var tip in pluginTipleri)
        {
            IPlugin plugin = (IPlugin)Activator.CreateInstance(tip);
            Console.WriteLine($"Eklenti: {plugin.Ad}");
            plugin.Calistir();
        }
    }
}

Bu yapı sayesinde yeni eklentiler derleme zamanında bilinmese bile çalışma zamanında sisteme dahil edilebilir.


TL;DR

  • Reflection: Çalışma zamanında tip bilgisi edinme ve dinamik erişim sağlar (Type, MethodInfo, PropertyInfo vb.).
  • Late Binding: Derleme anında bilinmeyen sınıfları çalışma anında yükleyip kullanma işlemidir.
  • Assembly.LoadFrom() ile harici DLL’ler yüklenip dinamik olarak çağrılabilir.
  • Private üyelere erişmek için BindingFlags kullanılabilir.
  • Performans maliyeti yüksektir — sadece gerekli durumlarda kullanılmalıdır.
  • Gerçek dünyada plugin, serializer, ORM ve test framework’lerinde sıkça kullanılır.

İlişkili Makaleler

C# ile SOLID Prensipleri

C# örnekleriyle SOLID prensiplerinin uygulanışı: daha esnek, sürdürülebilir ve test edilebilir kod tasarımları.