Skip to content

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ı

  1. Tip Bilgisi İnceleme
  2. Bir tipin özelliklerini, metodlarını ve alanlarını keşfetme
  3. Tip hiyerarşisini inceleme
  4. Attribute'ları okuma

  5. Dinamik Tip Oluşturma

  6. Çalışma zamanında yeni tip örnekleri oluşturma
  7. Interface'leri dinamik olarak implemente etme
  8. Proxy nesneleri oluşturma

  9. Dinamik Metod Çağırma

  10. Metodları isimlerine göre çağırma
  11. Private üyelere erişim
  12. 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

  1. Performans
  2. Reflection işlemleri normal kod çağrılarına göre daha yavaştır
  3. Sık kullanılan reflection işlemleri için cache mekanizması kullanılmalıdır

  4. Güvenlik

  5. Private üyelere erişim sağlayabildiği için dikkatli kullanılmalıdır
  6. Güvenlik kontrolleri yapılmalıdır

  7. Bakım

  8. Reflection kullanılan kodlar daha zor debug edilebilir
  9. Refactoring işlemleri daha zor olabilir

Best Practices

  1. 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;
    }
    

  2. 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);
    }
    

  3. 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ı

  1. Dependency Injection Framework'leri
  2. Tip bağımlılıklarını otomatik çözme
  3. Constructor injection için reflection kullanımı

  4. ORM (Object-Relational Mapping)

  5. Entity property'lerini otomatik eşleştirme
  6. Dinamik sorgu oluşturma

  7. Serialization/Deserialization

  8. JSON/XML dönüşümleri
  9. Custom serializer implementasyonları

  10. Plugin Sistemleri

  11. Dinamik olarak yüklenen assembly'leri keşfetme
  12. Interface implementasyonlarını bulma

  13. Unit Testing Framework'leri

  14. Test metodlarını otomatik bulma
  15. Test fixture'ları oluşturma

Performans İyileştirmeleri

  1. 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();
    }
    

  2. 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ı

  1. Code Access Security (CAS)
  2. ReflectionPermission kontrolü
  3. Kısıtlı reflection erişimi

  4. 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);
    }
    

  5. 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

  1. 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;
    }
    

  2. Custom Attribute Oluşturma

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class MyCustomAttribute : Attribute
    {
        public string Description { get; }
    
        public MyCustomAttribute(string description)
        {
            Description = description;
        }
    }
    

  3. 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);
    }
    

Kaynaklar