Birleştirme
Tüm katmanları birleştirerek çalışan bir mini framework yazarsın.
Birleştirme
Son ders tüm parçaları birleştirir. Şu ana kadar komut deseni, async, reflection, öznitelik, DI kabı ve test gördük. Şimdi bir Runner sınıfı ekleyip container'daki tüm komutları sırayla çalıştıracağız.
Runner, Container'ı alır; async Task RunAllAsync() metodu container'daki her komut adını dolaşır, çözer, await cmd.ExecuteAsync() ile çalıştırır ve "{name}: {result}" biçiminde yazdırır. Main artık tek komut değil, tüm kayıtlı komutları çalıştırır. Bu, gerçek bir uygulamanın iskeletidir.
Container'a Names özelliği
Runner'ın tüm komutları dolaşması için container'ın kayıtlı adları dışarı açması gerekir. public IEnumerable<string> Names => _factories.Keys; ile bu sağlanır. IEnumerable<string> yalnızca okuma yapısını vurgular; dışarıdaki kod sözlüğü değiştiremez.
Runner bu Names üzerinde foreach ile dolaşır. Her ad için _container.Resolve<ICommand>(name) çağrısı yapar; sonuç bir ICommand örneğidir. await ile çalıştırır ve çıktıyı yazar. Bu, async + DI + reflection'ın gerçek bir bütün oluşturduğu andır.
Uygulama Runner ve Names ekle
Container sınıfına public IEnumerable<string> Names => _factories.Keys; özelliğini ekle. Runner sınıfı tanımla: kurucu bir Container alsın; public async Task RunAllAsync() metodu _container.Names üzerinde foreach ile dolaşıp her ad için _container.Resolve<ICommand>(name) çağrısı yapsın, await cmd.ExecuteAsync() sonucunu Console.WriteLine($"{name}: {result}") ile yazdırsın. Main'de bir Container yarat, Register("hello", () => new HelloCommand()) ile kayıt yap, bir Runner yarat ve await runner.RunAllAsync() çağır.
Örnek çözümü göster
public IEnumerable<string> Names => _factories.Keys; ekle. class Runner { private readonly Container _container; public Runner(Container container) => _container = container; public async Task RunAllAsync() { foreach (var name in _container.Names) { var cmd = _container.Resolve<ICommand>(name); Console.WriteLine($"{name}: {await cmd.ExecuteAsync()}"); } } } yaz. Main'de: var container = new Container(); container.Register("hello", () => new HelloCommand()); var runner = new Runner(container); await runner.RunAllAsync();
Örnek çözüm:
using System;
using System.Threading.Tasks;
using System.Reflection;
using System.Collections.Generic;
[Command("hello")]
class HelloCommand : ICommand
{
public async Task<string> ExecuteAsync()
{
await Task.CompletedTask;
return "Merhaba";
}
}
class CommandAttribute : Attribute
{
public string Name { get; }
public CommandAttribute(string name) => Name = name;
}
interface ICommand
{
Task<string> ExecuteAsync();
}
class Container
{
private readonly Dictionary<string, Func<ICommand>> _factories = new();
public void Register<T>(string name, Func<T> factory) where T : class, ICommand =>
_factories[name] = () => factory();
public T Resolve<T>(string name) where T : class => (T)_factories[name]();
public IEnumerable<string> Names => _factories.Keys;
}
class Runner
{
private readonly Container _container;
public Runner(Container container) => _container = container;
public async Task RunAllAsync()
{
foreach (var name in _container.Names)
{
var cmd = _container.Resolve<ICommand>(name);
Console.WriteLine($"{name}: {await cmd.ExecuteAsync()}");
}
}
}
class Program
{
static async Task Main()
{
var container = new Container();
container.Register("hello", () => new HelloCommand());
var runner = new Runner(container);
await runner.RunAllAsync();
}
}
Uygulama İkinci komut ekle ve çalıştır
Mevcut yapıya ByeCommand : ICommand sınıfını ekle. Sınıf [Command("bye")] ile işaretlensin ve ExecuteAsync() metodu await Task.CompletedTask çağrısı yaparak "Hoşça kal" döndürsün. Main'de container.Register("bye", () => new ByeCommand()) ile ikinci komutu kaydet; Runner her iki komutu sırayla çalıştırsın. Names özelliği sayesinde foreach iki adı da dolaşır.
Örnek çözümü göster
ICommand { public async Task<string> ExecuteAsync() { await Task.CompletedTask; return "Hoşça kal"; } } yaz. Main'de container.Register("bye", () => new ByeCommand()); ekle.
Örnek çözüm:
using System;
using System.Threading.Tasks;
using System.Reflection;
using System.Collections.Generic;
[Command("hello")]
class HelloCommand : ICommand
{
public async Task<string> ExecuteAsync()
{
await Task.CompletedTask;
return "Merhaba";
}
}
[Command("bye")]
class ByeCommand : ICommand
{
public async Task<string> ExecuteAsync()
{
await Task.CompletedTask;
return "Hoşça kal";
}
}
class CommandAttribute : Attribute
{
public string Name { get; }
public CommandAttribute(string name) => Name = name;
}
interface ICommand
{
Task<string> ExecuteAsync();
}
class Container
{
private readonly Dictionary<string, Func<ICommand>> _factories = new();
public void Register<T>(string name, Func<T> factory) where T : class, ICommand =>
_factories[name] = () => factory();
public T Resolve<T>(string name) where T : class => (T)_factories[name]();
public IEnumerable<string> Names => _factories.Keys;
}
class Runner
{
private readonly Container _container;
public Runner(Container container) => _container = container;
public async Task RunAllAsync()
{
foreach (var name in _container.Names)
{
var cmd = _container.Resolve<ICommand>(name);
Console.WriteLine($"{name}: {await cmd.ExecuteAsync()}");
}
}
}
class Program
{
static async Task Main()
{
var container = new Container();
container.Register("hello", () => new HelloCommand());
container.Register("bye", () => new ByeCommand());
var runner = new Runner(container);
await runner.RunAllAsync();
}
}
Kendini test et
-
Runner.RunAllAsync ne yapar?
- Container'daki tüm komutları sırayla çalıştırır
- Yalnızca ilk komutu çalıştırır
- Komutları siler
- Yeni komut kaydeder
Cevabı göster
Container'daki tüm komutları sırayla çalıştırır — Doğru. RunAllAsync container'daki her komutu sırayla çözer ve çalıştırır.
-
Birleştirme parçalarını eşleştir
- Runner
- Komutları sırayla çalıştırır
- Names
- Kayıtlı adları açar
- RunAllAsync
- Tüm komutları çalıştırır
- foreach
- Adlar üzerinde dolaşır