CodeBlanks Logo Icon CodeBlanks

Reflection ve attribute

C# kursu · İleri seviye · Ders 81/83

Reflection ve özel attribute'larla komut işleme yazarsın.

Reflection ve attribute

İkinci derste komut tek başınaydı. Şimdi komutları öznitelik ile işaretleyip reflection ile keşfedeceğiz. [Command("hello")] özniteliği bir sınıfa ad verir; Assembly.GetExecutingAssembly().GetTypes() tüm türleri tarar; t.GetCustomAttribute<CommandAttribute>() özniteliği okur.

Sonuç: yeni bir komut eklemek için yalnızca [Command("ad")] ile işaretli yeni bir sınıf yazarsın. Main'i değiştirmezsin; reflection komutu otomatik bulur. Bu, açık-kapalı ilkesinin güçlü bir uygulamasıdır.

Komut özniteliği

CommandAttribute sınıfı Attribute'tan türetilir ve bir Name özelliği taşır. Kullanım: [Command("hello")]. Parantez içindeki değer kurucuya aktarılır. Öznitelik, sınıfa derleme zamanında ek meta veri katar; çalışma zamanında reflection ile okunur.

Önemli: AttributeUsage ile özniteliğin yalnızca sınıflara uygulanabilmesini kısıtlayabilirsin. Şimdilik varsayılan kullanım yeterli; ileride bu kısıtı ekleyebilirsin.

Uygulama Komutları reflection ile keşfet

Bir CommandAttribute : Attribute sınıfı tanımla; kurucudan string name alıp Name özelliğine atsın. HelloCommand sınıfının üzerine [Command("hello")] ekle. Main'de Assembly.GetExecutingAssembly().GetTypes() ile tüm türleri tara; her tür için t.GetCustomAttribute<CommandAttribute>() çağır. Özniteliği olan ve ICommand'ı uygulayan türleri bir Dictionary<string, Type>'a ekle. commands["hello"] ile türü al, Activator.CreateInstance ile örnekle, (ICommand) türüne çevir ve await cmd.ExecuteAsync() sonucunu yazdır.

Örnek çözümü göster
Attribute { public string Name { get; } public CommandAttribute(string name) => Name = name; } yaz. [Command("hello")] ile HelloCommand'ı işaretle. Main'de: var commands = new Dictionary<string, Type>(); foreach (var t in Assembly.GetExecutingAssembly().GetTypes()) { var attr = t.GetCustomAttribute<CommandAttribute>(); if (attr != null && typeof(ICommand).IsAssignableFrom(t)) commands[attr.Name] = t; } var type = commands["hello"]; var cmd = (ICommand)Activator.CreateInstance(type); Console.WriteLine(await cmd.ExecuteAsync());
Örnek çözüm:
using System;
using System.Threading.Tasks;
using System.Reflection;
using System.Collections.Generic;

[Command("hello")]
class HelloCommand : ICommand
{
    public async Task<string> ExecuteAsync()
    {
        await Task.CompletedTask;
        return "Merhaba";
    }
}

class CommandAttribute : Attribute
{
    public string Name { get; }
    public CommandAttribute(string name) => Name = name;
}

interface ICommand
{
    Task<string> ExecuteAsync();
}

class Program
{
    static async Task Main()
    {
        var commands = new Dictionary<string, Type>();
        foreach (var t in Assembly.GetExecutingAssembly().GetTypes())
        {
            var attr = t.GetCustomAttribute<CommandAttribute>();
            if (attr != null && typeof(ICommand).IsAssignableFrom(t))
                commands[attr.Name] = t;
        }

        var type = commands["hello"];
        var cmd = (ICommand)Activator.CreateInstance(type);
        Console.WriteLine(await cmd.ExecuteAsync());
    }
}

Kendini test et

  1. Reflection terimlerini eşleştir

    [Command("hello")]
    Sınıfı adıyla işaretler
    GetTypes()
    Tüm türleri tarar
    GetCustomAttribute<T>
    Özniteliği okur
    Activator.CreateInstance
    Türü örnekler
  2. Öznitelik kullanımını tamamla

    [Command("____")]
    class HelloCommand : ICommand { ... }
    Cevabı göster
    [Command("hello")]
    class HelloCommand : ICommand { ... }
  3. Reflection ile komut keşfi ne kazandırır?

    • Daha hızlı çalışma
    • Daha az kod yazma genel olarak
    • Statik tip güvenliği
    • Yeni komut eklemek Main'i değiştirmez
    Cevabı göster

    Yeni komut eklemek Main'i değiştirmez — Doğru. Reflection yeni komutu otomatik bulur; Main sabit kalır.

İleri seviye bölümündeki tüm dersler