Reflection¶
Genel Bakış¶
Reflection, .NET'te çalışma zamanında (runtime) tip bilgilerini inceleme, tip örnekleri oluşturma ve dinamik olarak metod çağırma gibi işlemleri yapmamızı sağlayan güçlü bir özelliktir. Bu özellik sayesinde, derleme zamanında bilinmeyen tipleri ve üyelerini çalışma zamanında keşfedebilir ve kullanabiliriz.
Temel Kullanım Alanları¶
- Tip Bilgisi İnceleme
- Bir tipin özelliklerini, metodlarını ve alanlarını keşfetme
- Tip hiyerarşisini inceleme
-
Attribute'ları okuma
-
Dinamik Tip Oluşturma
- Çalışma zamanında yeni tip örnekleri oluşturma
- Interface'leri dinamik olarak implemente etme
-
Proxy nesneleri oluşturma
-
Dinamik Metod Çağırma
- Metodları isimlerine göre çağırma
- Private üyelere erişim
- Generic metodları dinamik olarak çağırma
Örnek Kullanımlar¶
1. Tip Bilgisi İnceleme¶
Type type = typeof(MyClass);
// Özellikleri listeleme
foreach (PropertyInfo prop in type.GetProperties())
{
Console.WriteLine($"Property: {prop.Name}, Type: {prop.PropertyType}");
}
// Metodları listeleme
foreach (MethodInfo method in type.GetMethods())
{
Console.WriteLine($"Method: {method.Name}, Return Type: {method.ReturnType}");
}
// Attribute'ları okuma
foreach (Attribute attr in type.GetCustomAttributes())
{
Console.WriteLine($"Attribute: {attr.GetType().Name}");
}
2. Dinamik Tip Oluşturma¶
// Assembly'den tip yükleme
Assembly assembly = Assembly.Load("MyAssembly");
Type type = assembly.GetType("MyNamespace.MyClass");
// Tip örneği oluşturma
object instance = Activator.CreateInstance(type);
// Generic tip oluşturma
Type genericType = typeof(List<>);
Type constructedType = genericType.MakeGenericType(typeof(int));
object list = Activator.CreateInstance(constructedType);
3. Dinamik Metod Çağırma¶
// Metod bilgisini alma
MethodInfo method = type.GetMethod("MyMethod");
// Metodu çağırma
object result = method.Invoke(instance, new object[] { "param1", 42 });
// Generic metod çağırma
MethodInfo genericMethod = type.GetMethod("GenericMethod");
MethodInfo constructedMethod = genericMethod.MakeGenericMethod(typeof(string));
constructedMethod.Invoke(instance, new object[] { "value" });
Dikkat Edilmesi Gerekenler¶
- Performans
- Reflection işlemleri normal kod çağrılarına göre daha yavaştır
-
Sık kullanılan reflection işlemleri için cache mekanizması kullanılmalıdır
-
Güvenlik
- Private üyelere erişim sağlayabildiği için dikkatli kullanılmalıdır
-
Güvenlik kontrolleri yapılmalıdır
-
Bakım
- Reflection kullanılan kodlar daha zor debug edilebilir
- Refactoring işlemleri daha zor olabilir
Best Practices¶
-
Cache Kullanımı
private static readonly Dictionary<string, MethodInfo> _methodCache = new(); public MethodInfo GetCachedMethod(string methodName) { if (!_methodCache.TryGetValue(methodName, out MethodInfo method)) { method = typeof(MyClass).GetMethod(methodName); _methodCache[methodName] = method; } return method; }
-
Tip Güvenliği
public T CreateInstance<T>(string typeName) where T : class { Type type = Type.GetType(typeName); if (type == null || !typeof(T).IsAssignableFrom(type)) { throw new ArgumentException($"Type {typeName} is not valid"); } return (T)Activator.CreateInstance(type); }
-
Hata Yönetimi
try { MethodInfo method = type.GetMethod("MyMethod"); if (method == null) { throw new MissingMethodException($"Method MyMethod not found in type {type.Name}"); } return method.Invoke(instance, parameters); } catch (TargetInvocationException ex) { throw ex.InnerException ?? ex; }
Kullanım Senaryoları¶
- Dependency Injection Framework'leri
- Tip bağımlılıklarını otomatik çözme
-
Constructor injection için reflection kullanımı
-
ORM (Object-Relational Mapping)
- Entity property'lerini otomatik eşleştirme
-
Dinamik sorgu oluşturma
-
Serialization/Deserialization
- JSON/XML dönüşümleri
-
Custom serializer implementasyonları
-
Plugin Sistemleri
- Dinamik olarak yüklenen assembly'leri keşfetme
-
Interface implementasyonlarını bulma
-
Unit Testing Framework'leri
- Test metodlarını otomatik bulma
- Test fixture'ları oluşturma
Performans İyileştirmeleri¶
-
Expression Trees Kullanımı
private static readonly Dictionary<string, Func<object, object>> _propertyGetters = new(); public static Func<object, object> CreatePropertyGetter(PropertyInfo property) { var instance = Expression.Parameter(typeof(object), "instance"); var cast = Expression.Convert(instance, property.DeclaringType); var propertyAccess = Expression.Property(cast, property); var convert = Expression.Convert(propertyAccess, typeof(object)); return Expression.Lambda<Func<object, object>>(convert, instance).Compile(); }
-
Delegate Cache
private static readonly ConcurrentDictionary<MethodInfo, Delegate> _methodCache = new(); public static TDelegate CreateDelegate<TDelegate>(MethodInfo method) where TDelegate : Delegate { return (TDelegate)_methodCache.GetOrAdd(method, m => Delegate.CreateDelegate(typeof(TDelegate), m)); }
Güvenlik Konuları¶
- Code Access Security (CAS)
- ReflectionPermission kontrolü
-
Kısıtlı reflection erişimi
-
Private Member Erişimi
public static T GetPrivateField<T>(object instance, string fieldName) { var field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); return (T)field?.GetValue(instance); }
-
Assembly Yükleme Güvenliği
public static Assembly LoadAssemblySafely(string assemblyPath) { try { return Assembly.LoadFrom(assemblyPath); } catch (FileLoadException) { // Güvenlik politikası ihlali throw new SecurityException("Assembly yüklenemedi"); } }
İleri Seviye Konular¶
-
DynamicMethod ile IL Generation
public static DynamicMethod CreateDynamicMethod() { var method = new DynamicMethod("DynamicMethod", typeof(void), new[] { typeof(object) }); var il = method.GetILGenerator(); // IL kodları il.Emit(OpCodes.Ret); return method; }
-
Custom Attribute Oluşturma
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class MyCustomAttribute : Attribute { public string Description { get; } public MyCustomAttribute(string description) { Description = description; } }
-
Generic Tip Manipülasyonu
public static Type MakeGenericType(Type genericType, params Type[] typeArguments) { if (!genericType.IsGenericTypeDefinition) { throw new ArgumentException("Type must be a generic type definition"); } return genericType.MakeGenericType(typeArguments); }