Ich möchte Abhängigkeitsinjektion
in Asp.Net Core
implementieren. Nachdem ich diesen Code zur Methode ConfigureServices
hinzugefügt habe, funktionieren beide Wege.
Was ist der Unterschied zwischen den Methoden services.AddTransient
und service.AddScoped
in Asp.Net Core
?
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddScoped<IEmailSender, AuthMessageSender>();
}
TL;DR
Transiente Objekte sind immer anders; eine neue Instanz wird für jedem Controller und jedem Dienst.
Scoped-Objekte sind innerhalb einer Anfrage gleich, aber unterschiedlich über verschiedene Anfragen.
Singleton-Objekte sind für jedes Objekt und jede Anfrage gleich.
Zur Verdeutlichung zeigt dieses Beispiel aus asp.net docs den Unterschied:
Um den Unterschied zwischen diesen Lebenszeit- und Registrierungsoptionen zu verdeutlichen, betrachten wir eine einfache Schnittstelle, die eine oder mehrere Aufgaben als eine Operation mit einem eindeutigen Bezeichner, OperationId
, darstellt. Je nachdem, wie wir die Lebensdauer für diesen Dienst konfigurieren, wird der Container der anfragenden Klasse entweder die gleichen oder unterschiedliche Instanzen des Dienstes zur Verfügung stellen. Um deutlich zu machen, welche Lebensdauer angefordert wird, erstellen wir einen Typ pro Lebensdaueroption:
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
{
}
}
Wir implementieren diese Schnittstellen mit einer einzigen Klasse, Operation
, die eine Guid
in ihrem Konstruktor akzeptiert oder eine neue Guid
verwendet, wenn keine angegeben wird:
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;
}
}
Als nächstes wird in ConfigureServices
jeder Typ dem Container entsprechend seiner benannten Lebensdauer hinzugefügt:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
Man beachte, dass der Dienst IOperationSingletonInstance
eine bestimmte Instanz mit einer bekannten ID von Guid.Empty
verwendet, so dass klar ist, wann dieser Typ in Gebrauch ist. Wir haben auch einen OperationService
registriert, der von jedem der anderen Operation
Typen abhängt, so dass es innerhalb einer Anfrage klar ist, ob dieser Dienst die gleiche Instanz wie der Controller oder eine neue Instanz für jeden Operationstyp erhält. Alles, was dieser Dienst tut, ist, seine Abhängigkeiten als Eigenschaften offenzulegen, so dass sie in der Ansicht angezeigt werden können.
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;
}
}
}
Um die Objektlebensdauer innerhalb und zwischen einzelnen Anfragen an die Anwendung zu demonstrieren, enthält das Beispiel einen OperationsController
, der jede Art von IOperation
anfordert, sowie einen OperationService
. Die Aktion Index
zeigt dann alle OperationId
-Werte des Controllers und des Dienstes an.
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();
}
}
}
Jetzt werden zwei separate Anfragen an diese Controller-Aktion gestellt:
Beobachten Sie, welche der OperationId
-Werte innerhalb einer Anfrage und zwischen den Anfragen variieren.
Transiente Objekte sind immer anders; jedem Controller und jedem Dienst wird eine neue Instanz zur Verfügung gestellt.
Scoped-Objekte sind innerhalb einer Anfrage gleich, aber zwischen verschiedenen Anfragen unterschiedlich
Singleton-Objekte sind für jedes Objekt und jede Anfrage gleich (unabhängig davon, ob eine Instanz in ConfigureServices
bereitgestellt wird)
In dotnet's dependency injection gibt es 3 Hauptlebensdauern:
Singleton, das eine einzige Instanz für die gesamte Anwendung erzeugt. Es erstellt die Instanz zum ersten Mal und verwendet das gleiche Objekt in allen Aufrufen wieder.
Scoped Lebenszeitdienste werden einmal pro Anfrage innerhalb des Bereichs erstellt. Es ist gleichbedeutend mit Singleton im aktuellen Bereich. z.B. in MVC wird 1 Instanz pro http-Anfrage erstellt, aber die gleiche Instanz wird in den anderen Aufrufen innerhalb der gleichen Webanfrage verwendet.
Transiente Lebensdauer Dienste werden bei jeder Anforderung erstellt. Diese Lebensdauer eignet sich am besten für leichtgewichtige, zustandslose Dienste.
Hier finden Sie einige Beispiele, die den Unterschied verdeutlichen:
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/
und hier ist der Link zur offiziellen Dokumentation:
Transient, scoped und singleton definieren den Prozess der Objekterstellung in ASP.NET MVC core DI, wenn mehrere Objekte desselben Typs injiziert werden müssen. Falls Sie noch nicht mit Dependency Injection vertraut sind, können Sie sich dieses [DI IOC Video][1] ansehen.
Sie können den folgenden Controller-Code sehen, in dem ich zwei Instanzen von "IDal" im Konstruktor angefordert habe. Transient , Scoped und Singleton definieren, ob dieselbe Instanz in "_dal" und "_dal1" injiziert wird oder nicht.
public class CustomerController : Controller
{
IDal dal = null;
public CustomerController(IDal _dal
,IDal _dal1)
{
dal = _dal;
// DI of MVC core
// inversion of control
}
}
Transient :- In transient werden neue Objektinstanzen in einer einzigen Anfrage und Antwort injiziert. Unten ist ein Schnappschuss, in dem ich GUID-Werte angezeigt habe.
Scoped :- In scoped wird dieselbe Objektinstanz in eine einzelne Anfrage und Antwort injiziert.
Singleton :- Bei Singleton wird dasselbe Objekt in alle Anfragen und Antworten injiziert. In diesem Fall wird eine globale Instanz des Objekts erstellt.
Nachfolgend finden Sie ein einfaches Diagramm, das die oben genannten Grundlagen visuell erklärt.
Das obige Bild wurde von SBSS-Team gezeichnet, wenn ich war unter ASP.NET MVC Ausbildung in Mumbai Ausbildung, ein großer Dank an SBSS-Team, um das obige Bild zu erstellen.