Detaylı Keyed DI Servisler

Selamlar,

Bu makalede .Net 8.0 ile gelen, bildiğiniz Dependency Injection mantığını değiştiren “Keyed DI Service”lerden detaylıca bahsedeceğiz.

Temel olarak, aynı servisleri farklı adlar altında birden çok kez kaydetme ve belirli bir tür/ad birleşimini enjekte etme olanağını bizlere sunuyor. Bunu mümkün kılmak için, eski dostumuz “IServiceProvider“‘ı iki yeni yöntemle genişleten yeni bir arayüz olan “IKeyedServiceProvider”’ı kullanıyor.

Gelin hemen bir örnek ile konuya dalalım: Bir kaç kullanıcıyı siteye ekleyip, filitreleyen bir servis yazalım

UserModel:

IUserService:

UserService: Aşağıda Constructorda, eğer UserListesi boş ise doldurulan bir UserServis görülmektedir. Ayrıca “GetUserByID()” ile, istenen User Filitrelenerek getirilmektedir.

Program.cs:

user” string keyword’ü ile Transient olarak ilgili IUserService, tanımlanmıştır.

Peki nasıl kullanıyoruz ?

UserController: Aşağıda görüldüğü gibi, User sınıfın Constructor’ında tanımlı birşey yoktur. Hatta User sınıfın constructor’ı bile yoktur :) Servisin kullanılacağı method’a “IUserService“,  “[FromKeyedServices(“user”)]” keyword’ü ile parametre olarak tanımlanmıştır. Ve ilgili servise ait methodlar, ilgili WebApi içerisinde kullanılmıştır.

Yukarıda dikkatinizi çekmek istediğim bir konu daha var. String bir keyword ile (‘User‘) ilgili servis çağrılmıştır. Yani ilgili aynı servis, başka bir keywordler ile de ya da string keyword değiştirilerek temsil ettiği farklı servis de, method’a parametre olarak verilebilirdi.

Şimdi biraz hayal gücümüzü zorlayalım ve bu “user” string keyword’ü configden alsak, method’a parametre olarak alınan servisi dinamik olarak değiştirebilir miyize hep beraber bakalım.

Şimdi gelin “WeatherService ve WeatherService2” adında iki servis oluşturalım.

Models:

IWeatherService:

WeatherService: Aşağıda görüldüğü gibi örnek amaçlı üç method tanımlanmıştır. WeatherService2’de de aynı methodlar vardır ama console’a farklı anlamak için bu sefer “WeatherService2” yazmaktadır.

program.cs: Bu sefer Weather ve Weather2 Servisleri, iki farklı string keyword ile aşağıdaki gib tanımladık. Ayrıca Configuration dosyasındaki “WeatherServiceOptions” kısmını tanımladık. Sıradaki amacımız Method içinde tanımlı servise parametresini config dosyadan alıp, çalışılacak servisi dinamik olarak değiştirmek.

appsettings.json: Başta tanımlı servis “weather” ile ilk servisdir.

WeatherServiceOptions:

WeatherForecastController: Controller’ın Constructor’inda IOptionsSnapshot interface’i ile ilgili config tanımlanmıştır. Amaç, config dosya değiştiği zaman anlık bu değişimden, kodun derlenmeden fark edilmesidir.

WeatherForecastController(2): Geldik esas amacımızı test edeceğimiz EndPoint’e. FromKeyedServices ile çağracağımız string’i, configden çağırmak maalesef ÇALIŞMAMAKTADIR. Bu tarz dinamik tanımlama, KeyedServislerinde Hatay neden olmaktadır. Tanimlanacak String maalesef static olarak yazilmalidir.

Ama çıkmadık candan ümit kesilmez :=) Farklı bir yaklaşım ile amacımıza ulaşmaya çalışalım.

Şimdiki örnekde Database DBContext’in Connection’ini değiştirebileceğimiz, bir yöntemi göstermek istiyorum.

program.cs: Aşağıda görüldüğü gibi NorthWindContext “AddKeyedScoped()” keyword’ü ile DBContext her ihtiyaç duyulduğunda tekrardan yaratılacaktır. Doğal olarak, connection string değişirse bu herseferinde fark edilecektir.

WeatherTestController.cs: Aşağıdaki controllerda NorthwindContext, scoped olarak çağrılmaktadır..

Şimdi sıra geldi son örneğimiz olan String Değişiminde KeyedServiceProvider ile Kullanılacak Servisin Değiştirilmesine

WeatherTestController.cs: Aşağıda görüldüğü gibi “IServiceProvider” dependency Injection ile Constructor’da alınmıştır.

ServiceType(Enum): Services tipini belirlemek amacı ile kullanılan Enum. İlgili enum parametre olarak verilerek, istenen servis dinamik olarak çağrılacaktır.

WeatherTestController.cs: Aşağıda görüldüğü gibi “_serviceProvider.GetRequiredKeyedService” ile parametrik olarak alınan enum serviceType’a göre, istenen servis dinamik olarak çağrılmıştır.

Yukarıda görüldüğü gibi, seçilen servis tipine göre “WeatherService” ve “WeatherService2” dinamik olarak değiştirilip çağrılabilmektedir.

Geldik bir makalenin daha sonuna, Bu makalede, Keyed DI Serviceler ile Dependency Incetion mantığına farklı bir bakış atmış olduk. Artık çağrılacak servislerimizi Constructor’da almak yerine, methodlara parametrik olarak kullanabileceğiz. Önceden yapamadığımız, aynı servisleri artık farklı keywordler ile projemize dahil edebileceğiz. Böylece parametreye göre farklı şekilde ayağa kalkacak tek bir servisi, farklı keywordler ile projemize implemente edebileceğiz. Ayrıca _serviceProvider kullanılarak, belirlenecek parametreler ile eklenecek olan servislerin dinamik olarak değişmesi sağlanabilmektedir. Son olarak Keyed DI Serviceler ile Dependency Incetion’a büyük esneklik getirilmiştir. Özellikle dağıtık yapılarda mikroservislerde, hem kod okunaklığı, alınacak servislerin methodlara parametre olarak verilmesi ile artmış hem de string parametreler ile farklı servislerin dinamik seçilmesi, ona büyük esneklik sağlamıştır.

Yeni bir makalede görüşmek üzere hepinize hoşçakalın.

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.