Ön Hazırlık ve Gereksinimler
Dinamik konfigürasyon yapısını kurabilmek için .NET 8 veya üzeri bir SDK sürümüne sahip olmanız gerekmektedir. Projenize gerekli paketleri eklemek için terminal üzerinden aşağıdaki komutları kullanabilirsiniz. Bu paketler, konfigürasyon sağlayıcılarını (provider) yönetmemizi sağlar.
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Configuration.Binder
Bu paketler, konfigürasyon verilerini okumak, bağlamak ve nesne modellerine eşlemek için temel yapı taşlarını sağlar. Projenizi oluştururken Microsoft.Extensions.Hosting kütüphanesini de eklemeniz, bağımlılık enjeksiyonu (Dependency Injection) süreçlerini kolaylaştıracaktır.
IConfiguration ve IOptions Pattern Kullanımı
C# içerisinde konfigürasyon yönetimi için en güvenli ve temiz yol IOptions desenidir. Bu desen, ayarların uygulama genelinde tip güvenli (type-safe) bir şekilde kullanılmasını sağlar. İlk olarak, ayarlarınızı temsil edecek bir sınıf tanımlayalım.
public class UygulamaAyarlari
{
public string ServisUrl { get; set; } = string.Empty;
public int GecikmeSuresi { get; set; }
}
Yukarıdaki sınıf, konfigürasyon dosyanızdaki anahtarlar ile birebir eşleşmelidir. Bu yapı sayesinde, ayarları doğrudan string anahtarlarıyla çağırmak yerine, nesne üzerinden erişim sağlayarak hata yapma riskinizi minimize edersiniz.
Adım Adım Dinamik JSON Konfigürasyonu
Dinamik yapılandırmanın en önemli parçası, dosya değiştiğinde uygulamanın bunu algılamasıdır. reloadOnChange: true parametresi, konfigürasyon sağlayıcısının dosya sistemini izlemesini sağlar.
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
IConfiguration configuration = builder.Build();
Bu kod bloğu, appsettings.json dosyasındaki bir değişiklik olduğunda uygulamanın bu değişikliği otomatik olarak belleğe almasını sağlar. reloadOnChange özelliği, dosya sistemindeki dosya değişikliği olaylarını dinleyen bir FileSystemWatcher başlatır.
Konfigürasyon Değişimlerini İzleme
Uygulamanızın ayarlar güncellendiğinde tetiklenmesini istiyorsanız, IOptionsMonitor arayüzünü kullanmalısınız. Bu arayüz, çalışma zamanında güncel ayarlara erişmenize ve değişiklikleri dinlemenize olanak tanır.
public class ServisHizmetlisi
{
private readonly IOptionsMonitor _ayarlar;
public ServisHizmetlisi(IOptionsMonitor ayarlar)
{
_ayarlar = ayarlar;
// Ayarlar her değiştiğinde tetiklenir
_ayarlar.OnChange(yeniAyarlar => {
Console.WriteLine("Ayarlar güncellendi: " + yeniAyarlar.ServisUrl);
});
}
}
Bu yöntem, özellikle veritabanı bağlantı dizeleri veya API anahtarları gibi kritik veriler değiştiğinde, uygulamanın yeniden başlatılmadan yeni konfigürasyonu kullanmasını sağlar.
Konfigürasyon Yönetim Yöntemlerinin Karşılaştırılması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| IOptions | Hızlı ve basit, tek seferlik okuma | Dinamik güncellemeleri desteklemez |
| IOptionsSnapshot | Her istekte güncel ayar | Scoped servislerde çalışır |
| IOptionsMonitor | Dinamik, her an güncel | Biraz daha karmaşık yapı |
Güvenlik ve Kritik Uyarılar
Dikkat: Konfigürasyon dosyalarınızda asla şifre, API anahtarı veya gizli tokenları düz metin (plain-text) olarak saklamayın. Üretim ortamlarında (Production) Azure Key Vault, HashiCorp Vault veya .NET Secret Manager araçlarını kullanın. Dinamik konfigürasyon dosyalarını dışarıdan erişime kapalı dizinlerde tutun.
Özel Konfigürasyon Sağlayıcıları Oluşturma
Bazen ayarların bir JSON dosyasında değil, bir veritabanı tablosunda veya uzak bir API'de tutulması gerekir. Bunun için ConfigurationProvider sınıfından türetilen özel bir sağlayıcı yazabilirsiniz.
public class VeritabaniConfigurationProvider : ConfigurationProvider
{
public override void Load()
{
// Veritabanından verileri çek ve Data sözlüğüne ekle
Data["ServisUrl"] = "https://api.gercek.com";
}
}
Bu yaklaşım, merkezi bir konfigürasyon sunucusu yönetmek istediğinizde en esnek çözümdür. Uygulama, her başlangıçta veya periyodik olarak veritabanını sorgulayarak ayarları güncelleyebilir.
Sıkça Sorulan Sorular
IOptionsSnapshot ve IOptionsMonitor arasındaki fark nedir?
IOptionsSnapshot, bir HTTP isteği (request) süresince ayarların sabit kalmasını sağlar. IOptionsMonitor ise uygulama genelinde ve her an güncel ayarlara erişim sağlar, genellikle singleton servislerde tercih edilir.
Dinamik konfigürasyon performansı etkiler mi?
Dosya izleme ve veritabanı sorgulama işlemleri, çok sık gerçekleşmediği sürece performansı etkilemez. Ancak, her milisaniyede bir dosya okumak sistem kaynaklarını tüketebilir. Değişiklikleri sadece gerektiğinde tetiklemek önemlidir.
JSON dışındaki formatları kullanabilir miyim?
Evet, XML, YAML veya INI formatları için .NET ekosisteminde hazır sağlayıcılar mevcuttur. NuGet üzerinden ilgili paketleri yükleyerek ConfigurationBuilder'a ekleyebilirsiniz.
Konfigürasyon güncellenirken hata oluşursa ne olur?
Dinamik konfigürasyon yapısında, dosya formatı bozuksa (örneğin JSON syntax hatası), sağlayıcı güncellemeyi reddeder ve uygulama mevcut (eski) ayarlar ile çalışmaya devam eder. Bu, uygulamanın çökmesini engelleyen güvenli bir mekanizmadır.
Environment Variable (Ortam Değişkenleri) ile nasıl birleştirilir?
.AddEnvironmentVariables() metodunu ConfigurationBuilder zincirine ekleyerek, ortam değişkenlerinin JSON dosyasındaki ayarları ezmesini (override) sağlayabilirsiniz. Bu, Docker ve Kubernetes ortamları için standart bir yaklaşımdır.
İleri Düzey Senaryo: Merkezi Konfigürasyon Yönetimi ve Azure App Configuration
Dinamik konfigürasyon yapısını yerel dosyalardan bulut tabanlı bir sisteme taşımak, özellikle mikroservis mimarilerinde operasyonel yükü ciddi oranda azaltır. Azure App Configuration gibi servisler, konfigürasyonları merkezi bir noktadan yönetmenize ve uygulama yeniden başlatılmadan değerleri güncellemenize olanak tanır.
Bu entegrasyonu sağlamak için Microsoft.Extensions.Configuration.AzureAppConfiguration paketini projenize eklemeniz gerekir. Aşağıdaki örnek, uygulamanın başlatılma aşamasında merkezi konfigürasyonun nasıl dahil edileceğini göstermektedir:
// Program.cs içerisine eklenmesi gereken yapı
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddAzureAppConfiguration(options =>
{
options.Connect(builder.Configuration["ConnectionStrings:AppConfig"])
.ConfigureRefresh(refresh =>
{
refresh.Register("SentinelKey", refreshAll: true)
.SetCacheExpiration(TimeSpan.FromSeconds(30));
});
});
builder.Services.AddAzureAppConfiguration();
Buradaki SentinelKey mantığı, merkezi konfigürasyonunuzda bir "tetikleyici" anahtar oluşturmanızı sağlar. Bu anahtarın değerini değiştirdiğinizde, uygulamanızdaki tüm konfigürasyonlar otomatik olarak yenilenir.
Konfigürasyon Yönetiminde Hata Ayıklama ve İzleme
Dinamik konfigürasyonlar bazen beklenmedik değerlerin atanmasına veya uygulama hatalarına yol açabilir. Bu durumları yönetmek için konfigürasyon sağlayıcılarını izlemek ve hataları loglamak kritik öneme sahiptir.
Doğrulama (Validation) Mekanizması
Konfigürasyon değerlerinin uygulama başlamadan veya güncellenmeden önce geçerli olup olmadığını kontrol etmek için DataAnnotation veya FluentValidation kullanabilirsiniz. IOptions arayüzü ile birlikte ValidateDataAnnotations metodunu kullanmak, hatalı yapılandırmaları anında tespit etmenizi sağlar:
// Startup.cs veya Program.cs içerisinde konfigürasyon doğrulama
builder.Services.AddOptions()
.Bind(builder.Configuration.GetSection("MySettings"))
.ValidateDataAnnotations()
.Validate(config =>
{
return config.TimeoutSeconds > 0 && config.TimeoutSeconds < 3600;
}, "Timeout değeri 0 ile 3600 arasında olmalıdır.");
Konfigürasyon Değişimlerini İzleme
Uygulamanızın hangi konfigürasyon değerini ne zaman çektiğini izlemek için IConfigurationRoot nesnesini kullanarak mevcut tüm sağlayıcıları listeleyebilirsiniz. Bu, özellikle "Hangi ayar dosyası hangi değeri eziyor?" sorusunu yanıtlamak için en etkili yöntemdir:
public void LogCurrentConfiguration(IConfiguration configuration)
{
var root = (IConfigurationRoot)configuration;
foreach (var provider in root.Providers)
{
Console.WriteLine($"Sağlayıcı: {provider.ToString()}");
foreach (var key in provider.GetChildKeys(Enumerable.Empty(), null))
{
Console.WriteLine($" - {key}: {provider.TryGet(key, out var val)}");
}
}
}
Bu yöntem, karmaşık hiyerarşilerde hangi değerin en son uygulandığını ve hangi kaynağın (Environment Variable, JSON, KeyVault) öncelikli olduğunu anlamanızı sağlar. Özellikle Docker konteynerleri içinde çalışan uygulamalarda, ortam değişkenlerinin doğru şekilde enjekte edilip edilmediğini doğrulamak için bu debug metodunu kullanabilirsiniz.
Sonuç
C# ile dinamik konfigürasyon dosyası yönetimi, uygulamanızın esnekliğini ve bakım kolaylığını büyük ölçüde artırır. IOptionsMonitor kullanarak çalışma zamanında değişen ayarlara tepki verebilir, özel sağlayıcılar ile konfigürasyonlarınızı merkezi bir yerden yönetebilirsiniz. Bir sonraki adım olarak, bu yapıyı bir merkezi konfigürasyon sunucusu (örneğin Consul veya Azure App Configuration) ile entegre etmeyi deneyebilirsiniz.
Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamlarında konfigürasyon yönetimi yaparken, verilerin şifrelenmesi ve erişim yetkilendirmesi (IAM) gibi güvenlik katmanlarını mutlaka uygulamanız gerekmektedir.


Yorumlar (0)
Yorum Yaz