C# MİMARİSİ #29: Source Generators ile Derleme Zamanı (Compile-time) Kod Üretimi

Source Generators ile Derleme Zamanı (Compile-time) Kod Üretimi

Source Generators ile Derleme Zamanı (Compile-time) Kod Üretimi

Konunun Mimari Önemi ve Temel Çalışma Prensipleri

Source Generators, .NET dil platformuyla birlikte gelen güçlü bir teknolojidir. Bu, geliştiricilerin derleme zamanında (compile-time) kod üretme imkanı sunar. Bu, metotları, sınıfları veya diğer kod öğelerini otomatik olarak oluşturarak verimliliği artırır, kod tekrarını azaltır ve hataları erken tespit edilmesini sağlar. Source Generators, özellikle genel amaçlı kod parçaları, otomatikleştirilmiş serialization, veri erişim katmanı kodları gibi senaryolarda oldukça faydalıdır.

Kurumsal Projelerde Dikkat Edilmesi Gereken En İyi Pratikler (Best Practices)

  • Modüler ve Test Edilebilir Kod: Source Generators ile oluşturulan kodlar da modüler ve test edilebilir olmalıdır. Bu, kodun bakımını ve gelecekteki değişiklikleri yönetmek kolaylaştırır.
  • Performans Dikkat Edilmesi: Source Generators, derleme süresini artırabilir. Bu nedenle, gereksiz veya fazla karmaşık kod üretimi kaçınılmalıdır.
  • Belgelenmiş ve Dokumente Edilmiş: Source Generators tarafından üretilen kodlar, diğer geliştiriciler tarafından anlaşılabilir ve kullanılabilir olmalıdır. İyi belgeler ve dokumentasyon sağlar.
  • Version Control: Source Generators tarafından üretilen kodlar, versiyon kontrol sistemlerine dahil edilmeli ve doğru şekilde yönetilmeli.

Gerçek Dünya Senaryolarına Uygun Kod Bloğu Örneği

Aşağıda, bir Source Generator kullanarak basit bir JSON serialization kodu üreten basit bir örnek bulunmaktadır. Bu örnek, verilen bir sınıf için JSON serialization kodunu derleme zamanında otomatik olarak üretir.

        
<!--#region Source Generator Code-->
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Linq;

namespace JsonSerializationGenerator
{
    [Generator]
    public class JsonSerializationSourceGenerator : ISourceGenerator
    {
        public void Initialize(GeneratorInitializationContext context)
        {
            // No initialization required for this example
        }

        public void Execute(GeneratorExecutionContext context)
        {
            foreach (var syntaxTree in context.Compilation.SyntaxTrees)
            {
                var root = syntaxTree.GetRoot();
                var classDeclarations = root.DescendantNodes().OfType<ClassDeclarationSyntax>();

                foreach (var classDeclaration in classDeclarations)
                {
                    var className = classDeclaration.Identifier.Text;
                    var namespaceName = syntaxTree.GetRoot().DescendantNodes().OfType<NamespaceDeclarationSyntax>().FirstOrDefault()?.Name.ToString();
                    var methodName = $"Serialize{className}";

                    var methodBody = GenerateMethodBody(className);

                    var method = SyntaxFactory.MethodDeclaration(
                        SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.StringKeyword)),
                        methodName)
                        .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                        .WithBody(SyntaxFactory.Block(
                            SyntaxFactory.ParseStatement($"var json = new System.Text.StringBuilder();"),
                            methodBody,
                            SyntaxFactory.ParseStatement($"return json.ToString();")
                        ));

                    var newClassDeclaration = classDeclaration.AddMembers(method);

                    var updatedRoot = root.ReplaceNode(classDeclaration, newClassDeclaration);

                    context.AddSource($"{className}Serializer.g.cs", SourceText.From(updatedRoot.ToFullString(), Encoding.UTF8));
                }
            }
        }

        private SyntaxNode GenerateMethodBody(string className)
        {
            var properties = typeof(T).GetProperties();

            var statements = new List<StatementSyntax>();

            foreach (var property in properties)
            {
                statements.Add(SyntaxFactory.ParseStatement($"json.Append(@\"\\\"{property.Name}\\\": \");"));
                statements.Add(SyntaxFactory.ParseStatement($"json.Append({property.Name}.ToString());"));
                statements.Add(SyntaxFactory.ParseStatement($"json.Append(\", \");"));
            }

            statements.RemoveAt(statements.Count - 1); // Remove the last comma

            return SyntaxFactory.Block(statements);
        }
    }
}
<!--#endregion-->
        
    

Performans Optimizasyonu ve Olası Darboğazlar

Source Generators, derleme süresini artırabilir. Bu nedenle, performans optimizasyonu için aşağıdaki stratejiler uygulanabilir:

  • Minimum Kod Üretimi: Source Generators tarafından üretilen kod, sade ve verimli olmalıdır. Gereksiz kod parçaları ve yinelenen kodlar kaçınılmalıdır.
  • Paralel İşleme: Source Generators, paralel olarak çalıştırılabilir. Bu, çoklu çekirdekli sistemlerde derleme süresini önemli ölçüde kısaltabilir.
  • Kod Analizi ve Profil Oluşturma:
NasuhAkay
NasuhAkay

Nasuh Akay, 20 yılı aşkın IT deneyimine sahip; kurumsal teknoloji çözümleri, ERP sistemleri, yazılım geliştirme, veri yönetimi ve dijital dönüşüm alanlarında çalışmalar yürüten bir teknoloji profesyonelidir.

Kariyeri boyunca farklı sektörlerde edindiği deneyimlerini; teknoloji, yazılım, veri mimarisi ve iş süreçlerinin geliştirilmesi üzerine yoğunlaştırmıştır.

Bu blogda ERP çözümleri, SQL Server, yazılım geliştirme, yapay zekâ, dijital dönüşüm ve teknoloji dünyasındaki gelişmeler üzerine bilgi, deneyim ve teknik paylaşımlarını okuyucularla buluşturmaktadır.

Amacı, karmaşık teknik konuları anlaşılır bir dille ele almak, gerçek hayatta karşılaşılan problemlere yönelik uygulanabilir çözümler sunmak ve teknoloji alanındaki bilgi birikimini paylaşmaktır.

Articles: 1062

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir