Yükleniyor...

C# Source Generators Kavramı (C# 9+)

C# Source Generators kavramını öğrenin. Derleme zamanında kod üretimi ve performans avantajları örneklerle açıklanıyor.

C# 9 ile birlikte tanıtılan Source Generators, derleme zamanında (compile-time) ek C# kodu üreten güçlü bir Roslyn özelliğidir. Bu mekanizma, kodun çalışma anında değil, derleme sırasında yeni kod dosyaları oluşturur. Böylece runtime maliyeti olmadan tekrarlayan kodlar otomatik üretilir, performans artar ve bakım yükü azalır.


Source Generator Nedir?

Source Generator, derleyiciye eklenecek bir bileşendir. Derleyici (Roslyn), projenizdeki kaynak kodu analiz eder, ihtiyaç duyulan yerlere otomatik olarak yeni sınıflar veya metotlar ekler. Üretilen kod, derleme aşamasında proje içine dahil olur ve geliştirici tarafından normal C# kodu gibi kullanılabilir.


// Özet: Source Generator bir derleyici eklentisidir.
// Geliştirici özel mantık yazar, generator kod üretir.
// Derleme sonunda oluşturulan kod otomatik olarak projeye eklenir.

Ne Zaman Kullanılır?


Basit Bir Source Generator Örneği

Aşağıda en basit haliyle çalışan bir Source Generator örneği bulunmaktadır. Bu generator, derleme sırasında yeni bir HelloGenerated sınıfı oluşturur.


// HelloGenerator.csproj (ayrı bir Class Library olmalı)
// Paket: Microsoft.CodeAnalysis.CSharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;

[Generator]
public class HelloGenerator : ISourceGenerator
{
    public void Initialize(GeneratorInitializationContext context)
    {
        // Gerekirse analiz başında çalışır (örneğin syntax dinleme)
    }

    public void Execute(GeneratorExecutionContext context)
    {
        string code = @"
namespace HelloGen
{
    public static class HelloGenerated
    {
        public static void SayHello() =>
            System.Console.WriteLine(""Merhaba! Bu sınıf derleme sırasında üretildi."");
    }
}";
        context.AddSource("HelloGenerated.g.cs", SourceText.From(code, Encoding.UTF8));
    }
}

// Ana projede kullanım
using HelloGen;

class Program
{
    static void Main()
    {
        HelloGenerated.SayHello(); // Derleme sırasında üretilen kodu çağırır
    }
}

Derleme sırasında bu kod dosyası otomatik oluşturulur. Visual Studio’da “Analyzers → HelloGenerator → HelloGenerated.g.cs” altında görülebilir.


Yapı: Generator Projesi Oluşturma

  1. Yeni bir Class Library (.NET Standard) projesi oluşturun.
  2. Proje dosyasına aşağıdaki özellikleri ekleyin:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>latest</LangVersion>
    <IncludeBuildOutput>false</IncludeBuildOutput>
    <AnalyzerLanguage>C#</AnalyzerLanguage>
    <OutputItemType>Analyzer</OutputItemType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" />
  </ItemGroup>
</Project>

Bu yapı sayesinde proje bir “Analyzer/Generator” olarak kullanılabilir hale gelir. Daha sonra bu DLL’i ana projeye “Analyzer” olarak referans verin.


Attribute Bazlı Kod Üretimi

Gerçek dünyada generator’lar genellikle attribute’lar aracılığıyla tetiklenir. Örneğin bir sınıfın üzerine [AutoToString] attribute’u eklediğinizde derleme sırasında otomatik bir ToString() metodu üretebilirsiniz.


// Kullanıcı kodu
[AutoToString]
public partial class Kisi
{
    public string Ad { get; set; }
    public int Yas { get; set; }
}

// Generator tarafından üretilen kod (derleme sırasında)
public partial class Kisi
{
    public override string ToString() =>
        $""Kisi: Ad={Ad}, Yas={Yas}"";
}

Bu yaklaşım, boilerplate (tekrarlayan) kodları ortadan kaldırarak bakım kolaylığı sağlar.


Incremental Source Generator (C# 10+)

C# 10 ile birlikte gelen Incremental Generator, performans ve incremental build desteği sunar. Yalnızca değişen dosyalar için kod yeniden üretilir.


using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Text;

[Generator]
public class BasitIncrementalGenerator : IIncrementalGenerator
{
    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        var sınıflar = context.SyntaxProvider
            .CreateSyntaxProvider(
                predicate: (syntaxNode, _) => syntaxNode is ClassDeclarationSyntax,
                transform: (ctx, _) => (ClassDeclarationSyntax)ctx.Node)
            .Collect();

        context.RegisterSourceOutput(sınıflar, (spc, sınıfListesi) =>
        {
            foreach (var sınıf in sınıfListesi)
            {
                string ad = sınıf.Identifier.Text;
                string kod = $@"
namespace AutoGen
{{
    public static class {ad}Info
    {{
        public static void Yaz() =>
            System.Console.WriteLine(""Sınıf: {ad}"");
    }}
}}";
                spc.AddSource($"{ad}Info.g.cs", SourceText.From(kod, Encoding.UTF8));
            }
        });
    }
}

Bu modelle büyük projelerde derleme performansı ciddi oranda artar. Artık generator’lar yalnızca etkilenmiş dosyalar için çalışır.


Source Generator vs Reflection

ÖzellikSource GeneratorReflection
Çalışma ZamanıDerleme Zamanı (Compile-time)Çalışma Zamanı (Runtime)
PerformansYüksek (kodu önceden üretir)Düşük (çalışma anında analiz)
Kullanım AlanıORM, Serialization, API ClientPlugin, Test, Dinamik Tipler
Kod GörünürlüğüÜretilen dosyalar proje içinde görülebilirYalnızca çalışma anında etkilidir

Performans ve Dikkat Edilecekler


Örnek: Otomatik DTO Üretimi

Örneğin bir veritabanı tablosuna karşılık gelen modellerden DTO sınıfları üretmek istediğinizi düşünün. Aşağıdaki Source Generator, her model için bir {ModelAdı}Dto sınıfı oluşturur.


// Model sınıfı
[AutoDto]
public class Kullanici
{
    public int Id { get; set; }
    public string Ad { get; set; }
}

// Üretilen kod
public class KullaniciDto
{
    public int Id { get; set; }
    public string Ad { get; set; }
}

Bu sayede manuel DTO yazma zahmeti ortadan kalkar, modeldeki değişiklikler otomatik yansır.


TL;DR

  • Source Generators, derleme sırasında kod üreten Roslyn tabanlı araçlardır.
  • Reflection gibi runtime maliyeti yoktur; performans ve güvenlik açısından daha verimlidir.
  • ISourceGenerator veya IIncrementalGenerator arayüzleriyle uygulanır.
  • Oluşturulan kodlar proje derlemesine dahil edilir ve normal C# kodu gibi çalışır.
  • Gerçek dünyada serializer, mapper, DTO generator veya API client üretimi için sıkça kullanılır.

İlişkili Makaleler

C# ile SOLID Prensipleri

C# örnekleriyle SOLID prensiplerinin uygulanışı: daha esnek, sürdürülebilir ve test edilebilir kod tasarımları.

C# Reflection ve Late Binding

C#’ta Reflection ve Late Binding kullanımını öğrenin. Runtime tip keşfi, dinamik çağrılar ve esnek yapıların örnekleri anlatılıyor.