ASP.Net Core*** içinde ***
dependency injection*** uygulamak istiyorum. Bu kodları ***
ConfigureServices`*** metoduna ekledikten sonra her iki yol da çalışıyor.
Asp.Net Coredaki *
services.AddTransient* ve *
service.AddScoped`* yöntemleri arasındaki fark nedir?
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddScoped<IEmailSender, AuthMessageSender>();
}
TL;DR
Geçici nesneler her zaman farklıdır; yeni bir örnek her kontrolör ve her servis.
Kapsamlı nesneler bir istek içinde aynıdır, ancak diğer isteklerde farklıdır farklı talepler.
Singleton nesneleri her nesne ve her istek için aynıdır.
Daha fazla açıklama için, asp.net docs'deki bu örnek farkı göstermektedir:
Bu yaşam süresi ve kayıt seçenekleri arasındaki farkı göstermek için, bir veya daha fazla görevi benzersiz bir tanımlayıcı olan OperationId
ile bir işlem olarak temsil eden basit bir arayüz düşünün. Bu hizmet için yaşam süresini nasıl yapılandırdığımıza bağlı olarak, konteyner talep eden sınıfa hizmetin aynı ya da farklı örneklerini sağlayacaktır. Hangi yaşam süresinin talep edildiğini açıkça belirtmek için, her yaşam süresi seçeneği için bir tip oluşturacağız:
using System;
namespace DependencyInjectionSample.Interfaces
{
public interface IOperation
{
Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}
}
Bu arayüzleri, kurucusunda bir Guid
kabul eden veya hiçbiri sağlanmamışsa yeni bir Guid
kullanan tek bir sınıf olan Operation
kullanarak uyguluyoruz:
using System;
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Classes
{
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
{
Guid _guid;
public Operation() : this(Guid.NewGuid())
{
}
public Operation(Guid guid)
{
_guid = guid;
}
public Guid OperationId => _guid;
}
}
Daha sonra, ConfigureServices
içinde, her tür, adlandırılmış yaşam süresine göre konteynere eklenir:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
IOperationSingletonInstancehizmetinin
Guid.Emptyolarak bilinen bir ID'ye sahip belirli bir örnek kullandığına dikkat edin, böylece bu türün kullanımda olduğu anlaşılacaktır. Ayrıca, diğer
Operationtürlerinin her birine bağlı olan bir
OperationService` kaydettik, böylece bu hizmetin her işlem türü için denetleyiciyle aynı örneği mi yoksa yeni bir örneği mi aldığı bir istek içinde netleşecektir. Bu hizmetin tek yaptığı, bağımlılıklarını özellikler olarak ortaya çıkarmaktır, böylece görünümde görüntülenebilirler.
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Services
{
public class OperationService
{
public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance SingletonInstanceOperation { get; }
public OperationService(IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}
}
}
Uygulamaya yapılan ayrı ayrı talepler içindeki ve arasındaki nesne yaşam sürelerini göstermek için örnek, her bir IOperation
türünü talep eden bir OperationsController
ve bir OperationService
içerir. Ardından Index
eylemi, denetleyicinin ve hizmetin OperationId
değerlerinin tümünü görüntüler.
using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
using Microsoft.AspNetCore.Mvc;
namespace DependencyInjectionSample.Controllers
{
public class OperationsController : Controller
{
private readonly OperationService _operationService;
private readonly IOperationTransient _transientOperation;
private readonly IOperationScoped _scopedOperation;
private readonly IOperationSingleton _singletonOperation;
private readonly IOperationSingletonInstance _singletonInstanceOperation;
public OperationsController(OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance singletonInstanceOperation)
{
_operationService = operationService;
_transientOperation = transientOperation;
_scopedOperation = scopedOperation;
_singletonOperation = singletonOperation;
_singletonInstanceOperation = singletonInstanceOperation;
}
public IActionResult Index()
{
// viewbag contains controller-requested services
ViewBag.Transient = _transientOperation;
ViewBag.Scoped = _scopedOperation;
ViewBag.Singleton = _singletonOperation;
ViewBag.SingletonInstance = _singletonInstanceOperation;
// operation service has its own requested services
ViewBag.Service = _operationService;
return View();
}
}
}
Şimdi bu denetleyici eylemine iki ayrı istek yapılır:
Bir istek içinde ve istekler arasında OperationId
değerlerinden hangisinin değiştiğini gözlemleyin.
Geçici nesneler her zaman farklıdır; her denetleyiciye ve her hizmete yeni bir örnek sağlanır.
Kapsamlı nesneler bir istek içinde aynıdır, ancak farklı istekler arasında farklıdır
Singleton nesneleri her nesne ve her istek için aynıdır (ConfigureServices
içinde bir örnek sağlanıp sağlanmadığına bakılmaksızın)
Dotnet'in bağımlılık enjeksiyonunda 3 ana yaşam süresi vardır:
Uygulama boyunca tek bir örnek oluşturan Singleton. Örneği ilk kez oluşturur ve tüm çağrılarda aynı nesneyi yeniden kullanır.
Kapsamlı ömür boyu hizmetler, kapsam dahilindeki her istek için bir kez oluşturulur. Mevcut kapsamdaki Singleton'a eşdeğerdir. örneğin MVC'de her http isteği başına 1 örnek oluşturur, ancak aynı web isteği içindeki diğer çağrılarda aynı örneği kullanır.
Geçici ömürlü hizmetler her talep edildiklerinde oluşturulur. Bu ömür hafif, durum bilgisi olmayan hizmetler için en iyi sonucu verir.
Burada farkı görmek için örnekler bulabilirsiniz:
http://dotnetliberty.com/index.php/2015/10/15/asp-net-5-mvc6-dependency-injection-in-6-steps/
https://codewala.net/2015/04/30/your-dependency-injection-ready-asp-net-asp-net-5/
ve bu da resmi belgelere giden bağlantıdır:
Transient, scoped ve singleton, ASP.NET MVC core DI'da aynı türden birden fazla nesnenin enjekte edilmesi gerektiğinde nesne oluşturma işlemini tanımlar. Bağımlılık enjekte etme konusunda yeniyseniz, bu [DI IOC videosu][1]'na bakabilirsiniz.
Yapıcıda iki "IDal" örneği talep ettiğim aşağıdaki denetleyici kodunu görebilirsiniz. Transient, Scoped ve Singleton, aynı örneğin "_dal" ve "_dal1" veya farklı olarak enjekte edilip edilmeyeceğini tanımlar.
public class CustomerController : Controller
{
IDal dal = null;
public CustomerController(IDal _dal
,IDal _dal1)
{
dal = _dal;
// DI of MVC core
// inversion of control
}
}
Transient :- Transient'te yeni nesne örnekleri tek bir İstek ve yanıta enjekte edilecektir. Aşağıda GUID değerlerini görüntülediğim bir anlık görüntü var.
Kapsamlı :- Kapsamlıda aynı nesne örneği tek bir istek ve yanıta enjekte edilecektir.
Singleton :- Singleton'da aynı nesne tüm istek ve yanıtlara enjekte edilecektir. Bu durumda nesnenin global bir örneği oluşturulacaktır.
Aşağıda, yukarıdaki temeli görsel olarak açıklayan basit bir diyagram yer almaktadır.
Yukarıdaki Resim, mumbai'de ASP.NET MVC eğitimi eğitimi alırken SBSS ekibi tarafından çizildi, yukarıdaki resmi oluşturmak için SBSS ekibine çok teşekkür ederim.