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
- Reflection güçlü ama yavaştır — doğrudan metot çağrısına göre 10–100 kat maliyetli olabilir.
- Performans kritik senaryolarda önceden keşfedilen
MethodInfonesnelerini saklayın (caching yapın). - Reflection, private üyelere erişebilir; bu nedenle güvenlik kısıtlamaları önemlidir.
dynamicveyaExpression<T>tabanlı alternatifler bazı durumlarda daha verimli olabilir.
Ö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,PropertyInfovb.). - 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
BindingFlagskullanı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ı.
C# Interface ve Abstract Sınıflar
C#’ta interface ve abstract sınıfları öğrenin. Farklarını, ne zaman hangisini kullanacağınızı ve tasarım senaryolarını örneklerle keşfedin.
C# Roslyn Compiler API ile Kod Analizi
C#’ta Roslyn Compiler API ile kod analizi yapmayı öğrenin. Syntax tree, analiz ve code generation senaryoları örneklerle.
C# Sınıf (Class), Object, Property ve Metotlar
C#’ta class, object, property ve metot kavramlarını öğrenin. Nesne yönelimli programlamanın temel yapı taşları örneklerle açıklanıyor.
C# Source Generators Kavramı (C# 9+)
C# Source Generators kavramını öğrenin. Derleme zamanında kod üretimi ve performans avantajları örneklerle açıklanıyor.
C# Tasarım Desenleri (Factory, Singleton, Repository, Observer vb.)
C#’ta Factory, Singleton, Repository ve Observer gibi tasarım desenlerini öğrenin. Esnek ve sürdürülebilir yazılım geliştirme örneklerle anlatılıyor.