Modern yazılım geliştirme, esnek ve dinamik çözümler üretebilme ihtiyacını beraberinde getirir. Uygulamalarımızda, hangi tipin veya metodun kullanılacağını derleme zamanında belirleyemediğimiz durumlar olabilir. İşte tam da bu noktada Reflection devreye girer. Reflection sayesinde; çalışma zamanında bir nesnenin yapısını inceleyebilir, dinamik olarak nesneler oluşturabilir ve metodları çağırabiliriz. Bu esneklik, özellikle plugin sistemleri, test frameworkleri ve dinamik yapılandırma gerektiren uygulamalarda büyük avantaj sağlar.
Reflection Nedir
Reflection, bir nesneye veya tipe çalışma anında (runtime) bakabilme ve onun hakkında bilgi alabilme veya onu kullanabilme özelliğidir. Yani: Normalde biz bir sınıfın özelliklerini yazarken biliriz:
Person p = new Person();
p.Name = "Fatih";
Ama reflection şunu der:
“Ben bu
Person
sınıfını yazarken bilmiyorum, ama program çalışırken öğrenmek ve ona göre işlem yapmak istiyorum.”
Gerçek hayattan örnek vericek olursak: Bir kargo kutusu düşünün üzerinde sadece barkod var ama içinde ne olduğunu bilmiyorsun. Elinde bir kutu tarayıcı (reflection) alıyorsun ve kutuyu tarıyorsun ve içindeki ürünün adı, içeriği, markası gibi bilgileri öğreniyorsun. Hatta istersen kutuyu açıp ürünle etkileşime bile geçebiliyorsun. İşte bu reflection hayattımızdaki tanımıdır.
System.Reflection
C#’ta reflection işlemleri, System.Reflection namespace’i üzerinden yapılır. Burada en çok kullanılan sınıfları ve fonksiyonlar şunlardır.
Type Sınıfı
Bir nesne ya da sınıf hakkında temel bilgi almak.
Type type = typeof(Person); // Türe göre
Type type2 = obj.GetType(); // Nesneye göre
Özellikleri:
Özellik | Açıklama |
---|---|
Name | Sınıf adı ("Person" ) |
Namespace | Bulunduğu namespace |
IsClass , IsAbstract , IsInterface | Tür kontrolü |
BaseType | Kalıtım ilişkisi |
GetProperties() | Property’leri döner |
GetMethods() | Metotları döner |
GetFields() | Field’ları döner |
GetConstructors() | Constructor’ları döner |
GetCustomAttributes() | Attribute’leri verir |
PropertyInfo Sınıfı
PropertyInfo prop = type.GetProperty("Name");
object value = prop.GetValue(obj); prop.SetValue(obj, "Fatih");
Özellikleri
Yöntem / Özellik | Açıklama |
---|---|
Name | Property adı |
PropertyType | Türü (örneğin string ) |
CanRead , CanWrite | Get/set kullanılabilir mi |
GetValue(object) | Değerini alır |
SetValue(object, value) | Değerini ayarlar |
MethodInfo Sınıfı
MethodInfo method = type.GetMethod("SayHello");
method.Invoke(obj, null);
Özellikleri:
Yöntem / Özellik | Açıklama |
---|---|
Name | Metot adı |
ReturnType | Geri dönüş tipi |
GetParameters() | Parametre listesini verir |
Invoke(object, object[]) | Metodu çağırır |
ConstructorInfo Sınıfı
ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
object instance = ctor.Invoke(null);
FieldInfo Sınıfı
FieldInfo field = type.GetField("myField", BindingFlags.NonPublic | BindingFlags.Instance); field.SetValue(obj, 42);
Private alanlara erişmek için mutlaka
BindingFlags
kullan.
Activator
object obj = Activator.CreateInstance(typeof(Person));
Özellikleri:
Yöntem | Açıklama |
---|---|
CreateInstance(Type) | Varsayılan constructor’la nesne oluşturur |
CreateInstance(Type, args) | Parametreli constructor’la nesne oluşturur |
BindingFlags – Üyeleri Kontrol Et
Reflection ile erişimde neyi görmek istediğini belirtirsin.
Sabit | Açıklama |
---|---|
Public | Public olanlar |
NonPublic | Private/internal olanlar |
Instance | Nesneye ait (non-static) üyeler |
Static | Static üyeler |
DeclaredOnly | Base class’tan gelenler hariç sadece tanımlananlar |
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
Custom Attributes Okuma
var attr = method.GetCustomAttribute<LogAttribute>();
var allAttrs = method.GetCustomAttributes(); // Tüm attribute'ler
Attribute varsa
null
dönmez, yoksanull
döner.
Örnek Tip Bilgilerinin Elde Edilmesi
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void Greet()
{
Console.WriteLine($"Merhaba, ben {Name} ve {Age} yaşındayım.");
}
}
class Program
{
static void Main()
{
// Person tipinin bilgilerini elde etme
Type personType = typeof(Person);
Console.WriteLine("Sınıf Adı: " + personType.Name);
Console.WriteLine("\nMetodlar:");
foreach (MethodInfo method in personType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Console.WriteLine("- " + method.Name);
}
Console.WriteLine("\nÖzellikler:");
foreach (PropertyInfo property in personType.GetProperties())
{
Console.WriteLine("- " + property.Name);
}
}
}
Örnek Dinamik Nesne Oluşturma ve Metod Çağırma
class Program
{
static void Main()
{
// Person tipinin bilgilerini elde etme
Type personType = typeof(Person);
// Çalışma zamanında Person nesnesi oluşturma
object personInstance = Activator.CreateInstance(personType);
// Özelliklere değer atama
PropertyInfo nameProp = personType.GetProperty("Name");
PropertyInfo ageProp = personType.GetProperty("Age");
nameProp.SetValue(personInstance, "Reflection Ali");
ageProp.SetValue(personInstance, 32);
// Greet metodunu dinamik olarak çağırma
MethodInfo greetMethod = personType.GetMethod("Greet");
greetMethod.Invoke(personInstance, null);
}
}
Örnek Private Üyeler Üzerinde İşlem Yapma
public class Secret
{
private string secretMessage = "Bu gizli mesaj!";
private void RevealSecret()
{
Console.WriteLine("Sır: " + secretMessage);
}
}
class Program
{
static void Main()
{
Type secretType = typeof(Secret);
object secretInstance = Activator.CreateInstance(secretType);
// Private alanı elde etme
FieldInfo field = secretType.GetField("secretMessage", BindingFlags.NonPublic | BindingFlags.Instance);
Console.WriteLine("Private Alan Değeri: " + field.GetValue(secretInstance));
// Private metodu çağırma
MethodInfo method = secretType.GetMethod("RevealSecret", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(secretInstance, null);
}
}