Menu
Coddy logo textTech

Attributes ve Reflection

Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 44 / 70.

Öznitelikler, sınıflar, metotlar veya özellikler gibi kod öğelerine eklediğiniz meta veri etiketleridir. Kodun nasıl doğrudan çalıştırıldığını değiştirmezler, ancak çalışma zamanında okunabilecek bilgiler sağlarlar. Yansıma, bu meta verileri okuyan mekanizmadır.

Bir niteliği, hedef öğenin üzerinde köşeli parantezler içine yerleştirerek uygularsın:

[Obsolete("Use NewMethod instead")]
public void OldMethod() { }

[Serializable]
public class Person
{
    public string Name { get; set; }
}

Attribute sınıfından kalıtım alarak özel öznitelikler oluşturabilirsin:

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

[Author("John")]
public class Calculator { }

Reflection, System.Reflection namespace'ini kullanarak çalışma zamanında türleri incelemenize ve öznitelikleri okumanıza olanak tanır:

Type type = typeof(Calculator);
var attr = type.GetCustomAttribute<AuthorAttribute>();
Console.WriteLine(attr.Name);  // John

You can also discover methods, özellikleri and invoke them dynamically:

MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
    Console.WriteLine(method.Name);

Attribute'lar ve reflection, birçok framework'ün temelini oluşturur: serileştirme kütüphaneleri JSON çıktısını denetlemek için bunları kullanır, test framework'leri test methods'larını keşfetmek için bunları kullanır ve bağımlılık enjeksiyonu container'ları servisleri otomatik olarak birbirine bağlamak için bunları kullanır.

challenge icon

Görev

Kolay

Özel attribute'ları ve reflection'ı kullanarak plugin olarak işaretlenmiş class'ları otomatik olarak bulup açıklayan bir plugin keşif sistemi oluşturalım. Bu, gerçek framework'lerin çalışma zamanında bileşenleri, test method'larını veya API uç noktalarını keşfetme biçimine benzer.

Code'unu üç dosyada düzenleyeceksin:

  • PluginAttribute.cs: PluginSystem namespace'inde PluginAttribute called bir özel attribute Create. Attribute'ın:
    • Attribute'dan Inherit etmesi
    • İki salt okunur özelliğe Have olması: Name (string) ve Version (string)
    • Her iki değeri constructor aracılığıyla Accept etmesi
  • Plugins.cs: PluginSystem namespace'inde several plugin class'ı Create. Bazıları PluginAttribute ile işaretlenmeli, biri ise işaretlenmemeli:
    • ImageProcessor - [Plugin("Image Processor", "1.0")] ile işaretlenmiş
    • DataExporter - [Plugin("Data Exporter", "2.5")] ile işaretlenmiş
    • HelperUtility - herhangi bir attribute ile işaretlenmemiş (bu yalnızca normal bir class)
    Her class boş olabilir - yalnızca reflection aracılığıyla metadata'larını keşfetmekle ilgileniyoruz.
  • Program.cs: Main dosyanda, PluginAttribute'a sahip tüm class'ları keşfetmek için reflection kullan. Keşfedilen her plugin için bilgilerini yazdır. Şunları yapman gerekecek:
    • current assembly'deki tüm type'ları al
    • each type için PluginAttribute'ı check et
    • attribute'ın Name ve Version özelliklerini çıkarıp görüntüle

Type'ları incelemek ve custom attribute'ları almak için System.Reflection kullan. GetCustomAttribute<T>() method'ı, attribute mevcut değilse null döndürür; böylece hangi class'ların gerçek plugin'ler olduğunu filtrelemek için bunu kullanabilirsin.

Keşfedilen her plugin'i, her satırda bir tane olacak şekilde şu formatta yazdır:

Plugin: {Name} (v{Version})

Plugin'ler şu sırayla yazdırılmalı: önce ImageProcessor, ardından DataExporter. HelperUtility class'ı attribute'a sahip olmadığı için çıktıda görünmemeli.

Beklenen çıktı:

Plugin: Image Processor (v1.0)
Plugin: Data Exporter (v2.5)

Bu challenge, framework'lerin attribute'ları işaretleyici olarak ve reflection'ı bunları keşfetmek için nasıl kullandığını gösterir - dependency injection container'larına, serialization library'lerine ve testing framework'lerine güç veren teknik de aynıdır!

Kendin dene

using System;
using System.Reflection;
using PluginSystem;

class Program
{
    public static void Main(string[] args)
    {
        // TODO: Mevcut assembly'den tüm tipleri al
        // Hint: Assembly.GetExecutingAssembly().GetTypes() kullan
        
        // TODO: Her tipi döngüye al ve PluginAttribute'a sahip olup olmadığını kontrol et
        // Hint: type.GetCustomAttribute<PluginAttribute>() kullan
        
        // TODO: Öznitelik varsa, eklenti bilgisini şu formatta yazdır:
        // Plugin: {Name} (v{Version})
        
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C# derleyicisi