.NET 8 – Minimap API Source Generator’ı İnceleyelim
Merhaba,
Bu içeriğimizde .NET 8 ile gelmesi beklenen, AOT iş yüklerini(workloads) desteklemek için tanıtılmış olan Minimal API Source Generator‘ı inceliyor olacağız. O halde hiç vakit kaybetmeden buyurun başlayalım…
Minimal API’lar Nasıl Çalışırlar?
Malumunuz, Asp.NET Core mimarisinde uygulamanın başlangıç deneyimini daha minimum bir seviyeye çekebilmek için .NET 6’da Minimal API’lar tanıtılmıştı. Minimal API’lardan önce bir Asp.NET Core uygulamasını ayağa kaldırabilmek için hiç yoktan ‘Program.cs’ ile herhangi bir controller sınıfı üzerinde birden fazla kural eşliğinde bir çalışma gerçekleştirmemiz gerekiyordu. Minimal API’lar sayesinde buradaki komplekslik olabildiğince sadeleştirilerek controller sınıflarına ihtiyaç duyulmaksızın direkt olarak ‘Program.cs’ içerisinde action’ları tasarlayabilme imkanı elde etmiş bulunuyoruz.
Misal olarak Minimal API’lar ile basit bir ‘Merhaba dünya’ çalışması yapmak istiyorsak eğer aşağıdaki gibi bir kod inşa etmemiz yeterli olacaktır.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Merhaba dünya...");
app.Run();
Görüldüğü üzere oldukça basit bir şekilde, 4 satır eşliğinde bir Asp.NET Core uygulamasını rahatlıkla ayağa kaldırabiliyor ve mimarinin konfigürasyonlarıyla vakit kaybetmeksizin direkt operasyonlarımıza odaklanarak, çalışmalarımızı yürütebiliyoruz.
Evet, bu yapılanma sizlerin de katılacağı üzere oldukça pratik ve etkili olsa da ne yazık ki .NET 8’de bir sorun teşkil etmektedir ki, o da, AOT ile normal Minimal API’ların uyumsuz olmasıdır. Minimal API’lar da AOT derlemesini gerçekleştirmek istiyorsanız yakın zamanda klavyeye almış olduğumuz Minimal API Ahead of Time(AOT) Compilation Template başlıklı makalemizden de hatırlayacağınız üzere AOT template’i üzerinden çalışmanızı yapılandırmanız gerekmektedir.
Neden Bir Source Generator’a İhtiyacımız Var?
Ahead of Time(AOT) compilation, .NET 8’de başlıca üzerinde odaklanılmış özelliklerden birisidir diyebiliriz. Malumunuz, AOT ile derlenmiş .NET uygulamalarında Just in Time(JIT) compilation yoktur ve tüm derleme compile time’da gerçekleştirilmektedir. Bunun, uygulamanın başlangıç süresi açısından avantaj sağladığını bildiğimiz gibi uygun olmayan noktalarda ister istemez dezavantajları olduğunu da bilmekteyiz. Misal olarak; JIT’in olmaması demek ‘Plugin Architecture’ tabanlı uygulamaların olmaması demektir.
.NET 8’de minimal api’leri AOT ile uyumlu hale getirebilmek için source generator’ları kullanabileceğimiz farklı bir yaklaşım sergilememiz gereklidir. Peki bu ne demektir?, yani bizler aşağıdaki gibi zaten minimal api’ları tanımlayabiliyor ve kullanabiliyoruz;
app.MapGet("/", () => "Merhaba dünya...");
app.MapGet("/{name}", (string name) => $"Merhaba {name}...");
Birazdan göreceğiz ki, AOT’yi hedefleyen source generator’ların genel tasarımı, çağırdığınızı düşündüğünüz metodu AOT’ye daha uygun olan farklı bir metotla değiştirmesi üzerine kuruludur. Böylece AOT dostu metotlar oluşturulmakta ve reflection tabanlı API’lara nazaran bunlar tercih edilmektedir.
Minimal API Source Generator’ı Etkinleştirme
Minimal api source generator’ın temel amacı AOT dostu olmaktır. Bunun için yapılması gereken, uygulamada ‘PublishAot’ özelliğini <PublishAot>true</PublishAot> şeklinde etkinleştirmektir. Bu yapılandırma neticesinde source generator uygulamada otomatik olarak aktifleştirilmiş olacaktır.
AOT açıkça source generator’ın ana odak noktasıdır lakin AOT kullanmasınız bile başlangıç zamanı açısından iyileştirmeleri görebilirsiniz. Minimal api’ler, her handler’ın RequestDelegate kodunu runtime’da dinamik olarak oluşturmak yerine, source generator ile bunu önceden de yapabilirler ve böylece başlangıç ve ilk istek sürelerini hızlandırabilirler. Bunun için .csproj dosyasında <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> yapılandırması eşliğinde minimal api’lar da source generator’ı etkinleştirebilirsiniz.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <InvariantGlobalization>true</InvariantGlobalization> <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> </PropertyGroup> . . . </Project>
İşte bu kadar!
Kullandığımız bu source generator yapılanması sayesinde çalışma zamanından ziyade derleme zamanında kod üretilmekte ve böylece runtime’da ki iş yükünü daha da azaltabilmekteyiz. Bu pek büyük bir fark yaratmayacaktır belki ama, misal olarak serverless gibi uygulamalarda tam AOT’ye geçemediğiniz durumlarda illaki yararı olacağı kanaatindeyiz.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Başarılı anlatım olmuş hocam, teşekkürler.