Source generator
Source generator ile derleme zamanı kod üretirsin.
Source generator
Bu derste bir DTO üreteci simülasyonu ekleyeceğiz. DtoGenerator statik sınıfı, tür adlarından DTO sınıf tanımları üretir ve bunları bir listeye AddSource ile ekler. Bu, gerçek bir source generator'ın çekirdek akışını taklit eder.
Üretici, her isim için name + ".g.cs" ipucu adıyla bir sınıf tanımı yaratır. Main, üreticiyi üç adla çağırır ve hint adlarını yazdırır.
DtoGenerator sınıfı
DtoGenerator statik sınıfı üç üye içerir: bir List<(string Hint, string Source)> özelliği, bir AddSource(string, string) metodu ve bir Generate(string[]) metodu. Generate, her ismi .g.cs uzantısıyla listeye ekler.
Bu sınıf, source generator'ların derleme zamanı kod nasıl ürettiğini gösterir. Liste sırası ekleme sırasını korur; bu yüzden çıktı deterministiktir.
Uygulama DtoGenerator sınıfını ekle
Projeye static class DtoGenerator ekle. public static System.Collections.Generic.List<(string Hint, string Source)> Sources { get; } = new(); özelliği, public static void AddSource(string hintName, string source) metodu (içinde Sources.Add((hintName, source));) ve public static void Generate(string[] typeNames) metodu olsun. Generate gövdesinde foreach (var name in typeNames) ile AddSource(name + ".g.cs", $"public class {name}Dto {{ }}") çağır. Main'de DtoGenerator.Generate(new[] { "Info", "Warn", "Error" }) çağırıp foreach (var entry in DtoGenerator.Sources) ile entry.Hint'leri yazdır.
Örnek çözümü göster
DtoGenerator sınıfını ekle. Main'de DtoGenerator.Generate(new[] { "Info", "Warn", "Error" }); ve foreach (var entry in DtoGenerator.Sources) Console.WriteLine(entry.Hint);
Örnek çözüm:
using System;
using System.Linq;
static class LogProcessor
{
public static int ParseLevel(string level)
{
return level switch
{
"INFO" => 0,
"WARN" => 1,
"ERROR" => 2,
_ => -1
};
}
public static int CountByLevel(string[] logs, int targetLevel)
{
int count = 0;
foreach (var log in logs)
{
if (ParseLevel(log.Split(':')[0]) == targetLevel)
{
count++;
}
}
return count;
}
public static string ParseWithSpan(ReadOnlySpan<char> log)
{
int colon = log.IndexOf(':');
if (colon < 0) return "";
return log.Slice(0, colon).ToString();
}
public static unsafe int UnsafeSum(int a, int b)
{
int* pa = &a;
int* pb = &b;
return *pa + *pb;
}
public static async System.Threading.Tasks.Task Run(string[] logs)
{
var channel = System.Threading.Channels.Channel.CreateUnbounded<string>();
var counts = new System.Collections.Concurrent.ConcurrentDictionary<string, int>();
foreach (var log in logs)
{
await channel.Writer.WriteAsync(log);
}
channel.Writer.Complete();
await foreach (var log in channel.Reader.ReadAllAsync())
{
var level = ParseWithSpan(log.AsSpan());
counts.AddOrUpdate(level, 1, (_, n) => n + 1);
}
foreach (var kvp in counts.OrderBy(k => k.Key))
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
}
}
static class DtoGenerator
{
public static System.Collections.Generic.List<(string Hint, string Source)> Sources { get; } = new();
public static void AddSource(string hintName, string source)
{
Sources.Add((hintName, source));
}
public static void Generate(string[] typeNames)
{
foreach (var name in typeNames)
{
AddSource(name + ".g.cs", $"public class {name}Dto {{ }}");
}
}
}
class Program
{
static void Main()
{
Console.WriteLine("LogProcessor iskeleti hazır");
var logs = new[] { "INFO: a", "WARN: b", "INFO: c", "ERROR: d" };
Console.WriteLine(LogProcessor.CountByLevel(logs, 0));
Console.WriteLine(LogProcessor.ParseWithSpan("ERROR: disk".AsSpan()));
Console.WriteLine(LogProcessor.UnsafeSum(3, 4));
LogProcessor.Run(logs).Wait();
DtoGenerator.Generate(new[] { "Info", "Warn", "Error" });
foreach (var entry in DtoGenerator.Sources)
{
Console.WriteLine(entry.Hint);
}
}
}
Kendini test et
-
Source generator'ın amacı nedir?
- Çalışma zamanında reflection yapmak
- Dosya okumak
- Derleme zamanı kod üretmek
- Test yazmak
Cevabı göster
Derleme zamanı kod üretmek — Doğru. Source generator derleme zamanı kod üretir.
-
DtoGenerator adımlarını eşleştir
- Generate
- DTO sınıfları üret
- AddSource
- Üretilen kodu listeye ekle
- .g.cs
- Üretilen dosya uzantısı
-
AddSource çağrısını tamamla
AddSource(name + ____, source);Cevabı göster
AddSource(name + ".g.cs", source);