Asp.Net Core - Servis Ömrü

(Dependency LifeTimes)

İbrahim Demirli
Kodcular
4 min readJan 15, 2022

--

Herkese merhabalar ,

Hepimizin projelerinde farkında olmadan kullandığı, büyük çoğunlukla çok önemsemediğimiz fakat daha geniş çaplı uygulamalar geliştirirken ihtiyaç duyabileceğimiz “servis ömür”lerini örnek bir proje üzerinde anlatmaya çalışacağım.

Dependecy Injection

Servis ömürlerine geçmeden önce Dependency Injection kavramını iyi anlamamız gerekiyor. Oluşturacağımız servisleri genelde bu teknikle (DI) yapılandırıyor olacağız. (DI konusuna ayrıntılı olarak daha sonraki yazılarda değiniyor olacağım.)

Kısaca bahsetmek gerekirse, uygulamalarımızda bulunan karmaşık sınıfların birbiri ile olan bağımlılığını minimize etmek için kullandığımız bir tekniğin adıdır. Bu teknik bize kod tarafının daha sade, anlaşılır ve kullandığımız sınıfların genişletilebilir olmasına olanak sağlar. Yazılımcı tabiriyle , bir sınıfın içinde başka bir sınıfı “new”lemeden kullanılması gerektiğini savunur. Bağlı olduğu nesnenin ya constructor’ıyla ya da Setter methoduyla parametre olarak alınması gerektiğini vurgular. Detaylı olarak bilgi sahibi olmak isterseniz şimdilik buradan inceleyebilirsiniz.

Asp.Net Core tarafında Dependency Injection (DI) için varsayılan olarak Microsoft.Extensions.DependencyInjection kütüphanesi kullanılmaktadır. Bu kütüphane beraberinde bir çok özellik içerir.Performans anlamında da bize güçlü şekilde yardımcı olur. Eğer daha fazlasına ihtiyacınız olursa (Örneğin ; özelleştirilmiş servis ömürleri vs.) üçüncü parti uygulamaları entegre ederek de kullanabilirsiniz. Örnek projemizde varsayılan olarak gelen DI kütüphanesini kullanıyor olacağız.

Genel anlamda sınıflar , bağımlılıklarını “constructor” aracılığıyla bildirerek “Explicit Dependencies Principle” ilkesini takip eder. Bu yaklaşıma “constructor injection” denir. Biz de bu metodolojiyi kullanarak servislerimizi oluşturup davranışlarını inceliyor olacağız.

Asp.Net Core Web uygulaması oluştururken ihtiyaç duyabileceğimiz servisleri büyük çoğunlukta otomatik olarak gelen Startup sınıfının içinde bulunan ConfigureService methodunda tanımlarız.

Servis ömürleri

Projeyi oluştururken varsayılan olarak gelen DI kütüphanesi bize üç adet servis ömrü sunar. Asp.Net’te sunucuya gelen her request’le beraber yeni bir servis kapsamı oluşur , request sona erdiğinde bu request içindeki servisler isteğe bağlı olan servis kapsamı ile birlikte temizlenir.

Transient : Her istekte servisin yeni bir örneğini oluşturur.

Scoped : Her kapsam için yeni bir örnek oluşturur. (Her istek bir Kapsamdır). Kapsam dahilinde mevcut servisi yeniden kullanır.

Singleton : Uygulama ömrü boyunca yalnızca bir kez yeni bir servis oluşturur ve onu her yerde kullanır.

Bütün bunları daha anlaşılır hale getirebilmek için örnek projemize geçelim.

Örnek Proje

Akış diyagramında da görüldüğü gibi 3 ayrı servisi “constructor injection” yardımıyla HomeController’da alıp davranışlarını inceliyor olacağız. Servis ömürlerinin değişimini Guid yardımıyla göstereceğiz.

(Boş bir Asp.Net Core projesi oluşturduğumuzu varsayıyorum.)

Adımlar

  1. İlk olarak base interface’imiz “IWorkDependencyService” interface’ini oluşturuyoruz.Oluşturacağımız servis sınıfları bu interface’i kullanacak.

2. Servis için gerekli olan sınıflarımızı ve bunlara bağlı interface’leri oluşturuyoruz. (Gösterim amaçlı tek bir tanesi için oluşturdum.)

3. Tanımladığımız servislerin aynı kapsam içindeki davranışlarını görmek için başka bir sınıfın içinde inject ederek uygulamanın ayağa kalktığı ve servis kapsamlarının (request <-> kapsam) oluştuğu andaki guid değerlerini izliyor olacağız.

4. Son olarak bu servisleri Startup sınıfının içinde tanımlıyor olmamız gerekiyor.

5. Tanımladığımız servisleri ilgili Controller’a inject edip alıyoruz. (HomeController)

6. Guid değerlerini, göstereceğimiz sayfalara ViewBag aracılığıyla taşıyoruz.

Örnek projeyi tamamladığımıza göre guid’lerin, servislerin çözümlenme durumuna göre nasıl değiştiğini inceleyelim.

Sayfa açıldığı ilk anda “Home” sayfamız ayağa kalkacak.

Servislerin davranış durumlarına bakalım ;

Scoped : Aynı kapsam içinde guid değerlerinde değişme olmamış. Bir nevi singleton gibi davranmış fakat bunun sebebi tek kapsam için bir sefer örnekleniyor olmasından kaynaklanıyor. (Farklı bir request attığımızda değiştiğini göreceğiz.)

Transient : Tek kapsamda iki farklı guid görüyoruz. Tek kapsam olmasına rağmen iki kez istendiği için iki farklı şekilde örneklenir.

Singleton : Uygulama ayağa kalkarken bir kez örneklenir , ve bunu her yerde kullanır. Scoped’tan farklı kapsam değiştikçe değişmez.

Şimdi uygulama ayaktayken Privacy sayfasına gidip istekte bulunalım ve çıktıları görüp karşılaştıralım.

Scoped : Kapsam değişti ve bir kez daha örneklendi.

Transient : Kapsam değişti ve iki farklı yerden istendiği için iki kez örneklendi.

Singleton : Herhangi bir değişiklik olmadı. Çünkü uygulama ayağa kalkarken bir kez örneklendi ve bunu diğer sayfa için de kullandı.

Bitirirken

Bu yazımda DI ile birlikte gelen servis ömürlerini anlatmaya çalıştım. Çok büyük projeler geliştirirken büyük sınıflarla çalışabiliriz ve bunların bağımlılıklarını iyi bir şekilde yönetmek performans olarak bize oldukça yarar getirecektir.

Umarım faydalı olmuştur.

Başka bir yazıda görüşmek üzere…

KAYNAKLAR

--

--

İbrahim Demirli
Kodcular

software || reader || thinker || writer || always a student