Asp.NET Core – Options Pattern
Merhaba,
Asp.NET Core, konfigürasyonel ayarları uygulamaya hızlı bir şekilde enjekte edebilmemiz için Options Pattern’i bizlere sunmaktadır. Bu desen sayesinde “appsettings.json” dosyasındaki kayıtları yapılandırılmış bir şekilde uygulamaya Dependency Injection ile dahil edebilmekte ve pratik bir şekilde talep ederek, kullanabilmekteyiz.
Hızlı bir örneklendirme yapabilmek için herhangi bir Asp.NET Core uygulamasındaki “appsettings.json” dosyasında aşağıdaki formatta kayıtlar tutalım.
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Teacher": { "Name": "Gençay", "No": 110355, "Lessons": [ { "Name": "C#" }, { "Name": "Asp.NET Core" }, { "Name": "SQL Server" } ] } }
Yukarıdaki “appsettings.json” dosyasının içeriğinde 10. satırdaki kayda bakarsanız bir öğretmene dair bilgileri barındıran json format yapısını göreceksiniz. Uygulamada bu kayıtlara ihtiyacımız olduğu taktirde Options Pattern olmaksızın aşağıdaki yöntemle uzun uzun ilgili verileri elde edebilmekteyiz.
public class HomeController : Controller { IConfiguration _configuration; public HomeController(IConfiguration configuration) { string teacher = configuration.GetSection("Teacher").Value; string teacherName = configuration.GetSection("Teacher:Name").Value; string teacher1Lesson = configuration.GetSection("Teacher:Lessons:0:Name").Value; string teacher2Lesson = configuration.GetSection("Teacher:Lessons:1:Name").Value; } }
ya da bu verileri karşılayacak bir model tasarlayarak aşağıdaki şekilde de çalışma gerçekleştirebiliriz;
public class Teacher { public int No { get; set; } public string Name { get; set; } public List<Lesson> Lessons { get; set; } }
public class Lesson { public string Name { get; set; } }
public class HomeController : Controller { IConfiguration _configuration; public HomeController(IConfiguration configuration) { Teacher teacher = configuration.GetSection("Teacher").Get<Teacher>(); } }
Evet, genellikle configürasyon ayarlarıyla birlikte statik verilerin tutulduğu dosya olan “appsettings.json” içerisinde verileri bu yöntemlerle basitçe edinebilmekte ve kullanabilmekteyiz. Madem bu yöntemlerle kayıtlar elde edilebiliyor, bu makale neyin nesi hoca? diye söylendiğinizi duyar gibiyim…
Düşünsenize… “appsettings.json” içerisindeki veriler bir iki yerde kullanılacaksa yukarıdaki yöntemlerden herhangi biriyle elde edilebilir ve tabi ki de bu yöntemler tercih edilmelidir. Ancak uygulamada birden fazla yerde kullanılacak veriler mevzu bahis olduğu durumlarda her veri okuma işlemini bu yöntemlerle gerçekleştirmek çok fazla kod tekrarına sebep olacak ve clean code mantığına aykırı bir durum doğuracaktır.
İşte bu tarz bir durumda Options Pattern stratejisi devreye girerek, uygulamada aşırı kullanılacak verileri kendilerine uygun tasarlanmış class modellerinden türetilen nesnelere yerleştirip ardından bu nesneleri uygulamanın dependency injection sağlayıcısına atanmasını ve istenildiği zaman bağımsız bir yaklaşımla elde edilmesini sağlamaktadır.
Stratejinin uygulanabilmesi için öncelikle “appsettings.json” dosyasındaki veriyi temsil edecek olan sınıflar tasarlanmalıdır. Bunun için yukarıda tanımladığımız “Teacher” ve “Lesson” sınıfları örneklendirmemiz için doğru tasarlanmıştır. İlgili sınıfları tekrar aşağıya alırsak eğer;
public class Teacher { public int No { get; set; } public string Name { get; set; } public List<Lesson> Lessons { get; set; } }
public class Lesson { public string Name { get; set; } }
Burada dikkat edilmesi gereken tek husus, options pattern’in json formatındaki verileri class instance’ına taşırken alan eşleşmesini kullanacağından dolayı sınıf yapısındaki property isimleri ile “appsettings.json” dosyasındaki alan isimlerinin birebir aynı olmasıdır. Aksi taktirde eşleşme başarısız olacağından dolayı ilgili instance’da belirtilen alanlar null olarak gelecektir.
Options pattern’i uygulayabilmek için uygulamanın ‘Startup.cs’ dosyasındaki ‘ConfigureServices’ metodu içerisinde aşağıdaki çalışma yapılmalıdır.
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.Configure<Teacher>(Configuration.GetSection("Teacher")); . . . } . . . }
Yukarıdaki kod bloğunu incelerseniz eğer ‘services’ parametresi üzerinden çağrılan ‘Configure’ metodu ile ‘appsettings.json’ dosyasındaki ‘Teacher’ alanı generic olarak belirtilen ‘Teacher’ nesnesine dönüştürülerek dependency injection providerına atanmıştır. Bu işlemden sonra ilgili veriler artık herhangi bir noktadan ‘IOptions<T>’ türünden istek yapılarak ilgili nesne türünde çağrılabilecek vaziyettedir.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
services.Configure metodu çağırıldığında ilgili class service kaydediliyor. Fakat Singleton olarak mı? GitHub da koduna baktım doğrudan verdiğimiz classı kaybetmiyor. Biliyorsanız sizden duymak isterim hocam.
Bildiğim kadarıyla Singleton.
Merhaba. Rica etsem soylermisiniz: IConfiguration ve IOptions farki nedir? ve hangisini ne zaman kullanmaliyiz?
IConfiguration
; environment’dan, secret.json’dan veyahut appsettings.json’dan verileri okumamızı sağlayan dahili bir arayüzken,IOptions<T>
ise bu içerikteki mevzu bahis olan Options Pattern’ı uygulamamızı sağlayan arayüzdür.IOptions => Singleton
IOptionsSnapshot => Scoped
IOptionsMonitor => Singleton
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-6.0 linkinde arkadaslar cok güzel detayli bilgi vermisler.
Merhaba, Teacher teacher = configuration.GetSection(“Teacher”).Get(); Buradaki Get metodunda hata alıyorum acaba nedeni nedir?