Saya ingin menerapkan dependency injection
di Asp.Net Core
. Jadi setelah menambahkan kode ini untuk ConfigureServices
metode, baik cara kerja.
Apa perbedaan antara pelayanan.AddTransient
dan layanan.AddScoped
metode dalam Asp.Net Core
?
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddScoped<IEmailSender, AuthMessageSender>();
}
TL;DR
Sementara benda-benda yang selalu berbeda; contoh baru disediakan untuk setiap kontrol dan setiap layanan.
Cakupan objek yang sama dalam permintaan, tetapi yang berbeda di seluruh permintaan yang berbeda.
Singleton benda adalah sama untuk setiap obyek dan setiap permintaan.
Untuk klarifikasi lebih lanjut, ini contoh dari asp.net docs menunjukkan perbedaan :
Untuk menunjukkan perbedaan antara ini seumur hidup dan pendaftaran pilihan, mempertimbangkan antarmuka yang sederhana yang mewakili satu atau lebih tugas-tugas sebagai suatu operasi dengan pengenal unik, OperationId
. Tergantung pada bagaimana kita mengkonfigurasi seumur hidup untuk layanan ini, wadah akan memberikan baik sama atau kasus yang berbeda dari layanan untuk meminta kelas. Untuk membuat jelas yang seumur hidup yang diminta, kita akan menciptakan salah satu jenis per seumur hidup pilihan:
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
{
}
}
Kami menerapkan antarmuka ini menggunakan satu kelas, Operasi
, yang menerima Guid
dalam konstruktor, atau menggunakan baru Guid
jika tidak ada disediakan :
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;
}
}
Selanjutnya, dalam ConfigureServices
, masing-masing jenis ditambahkan ke wadah sesuai dengan namanya seumur hidup:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
Perhatikan bahwa IOperationSingletonInstance
pelayanan dengan menggunakan contoh yang spesifik yang dikenal dengan ID Guid.Kosong
sehingga akan menjadi jelas ketika jenis ini di gunakan. Kami juga telah terdaftar OperationService
yang tergantung pada masing-masing dari yang lain Operasi
jenis, sehingga hal itu akan menjadi jelas dalam permintaan apakah layanan ini mendapatkan contoh yang sama seperti controller, atau yang baru, untuk setiap jenis operasi. Semua layanan ini tidak mengekspos dependensi sebagai sifat, sehingga mereka dapat ditampilkan di view.
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;
}
}
}
Untuk menunjukkan objek yang hidup di dalam dan di antara individu yang terpisah permintaan untuk aplikasi, sampel termasuk OperationsController
yang meminta masing-masing jenis IOperation
jenis serta OperationService
. Index
aksi kemudian menampilkan semua controller dan layanan OperationId
nilai-nilai.
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();
}
}
}
Sekarang dua permintaan yang dibuat untuk ini aksi controller:
Mengamati mana yang OperationId
nilai-nilai bervariasi dalam permintaan, dan antara permintaan.
Cakupan objek yang sama dalam permintaan, tetapi yang berbeda di berbagai permintaan
ConfigureServices
)Di dotnet's dependency injection ada 3 utama hidup :
Singleton yang menciptakan satu contoh di seluruh aplikasi. Ini menciptakan instance untuk pertama kalinya dan menggunakan kembali objek yang sama dalam semua panggilan.
Cakupan seumur hidup layanan yang dibuat sekali per permintaan dalam lingkup. Hal ini setara dengan Singleton dalam lingkup saat ini. misalnya. dalam MVC menciptakan 1 contoh per setiap permintaan http tetapi menggunakan contoh yang sama dalam panggilan lain dalam web yang sama permintaan.
Sementara seumur hidup layanan yang dibuat setiap kali mereka diminta. Hidup ini karya-karya terbaik yang ringan dan bernegara jasa.
Di sini anda dapat menemukan dan contoh-contoh untuk melihat perbedaannya :
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/
dan ini adalah link dokumentasi resmi :
Biasanya kode permintaan harus dibuat melalui sebuah konstruktor parameter, seperti di
public MyConsumingClass(IDependency dependency)
Yang ingin saya tekankan di @akazemis's jawaban yang "layanan" dalam konteks DI tidak berarti Tenang jasa; layanan implementasi dari dependensi yang menyediakan fungsionalitas.
Sementara , cakupan dan singleton mendefinisikan objek proses pembuatan di ASP.NET MVC core DI saat beberapa objek dari jenis yang sama yang harus disuntikkan. Dalam kasus anda baru untuk injeksi Ketergantungan yang anda lihat ini [DI IOC video][1]
Anda dapat melihat di bawah controller kode di mana saya telah meminta dua contoh dari "IDal" dalam konstruktor. Sementara , Cakupan dan Singleton menentukan apabila contoh sama akan disuntikkan di "_dal" dan "_dal1" atau berbeda.
public class CustomerController : Controller
{
IDal dal = null;
public CustomerController(IDal _dal
,IDal _dal1)
{
dal = _dal;
// DI of MVC core
// inversion of control
}
}
Transient :- Di transien baru instance objek yang akan disuntikkan di satu Permintaan dan respon. Di bawah ini adalah cuplikan gambar di mana saya ditampilkan nilai GUID.
Cakupan :- Dalam cakupan objek yang sama misalnya akan disuntikkan di satu permintaan dan respon.
Singleton :- Di Singleton objek yang sama akan disuntikkan di semua permintaan dan respon. Dalam hal ini salah satu global instance dari objek yang akan dibuat.
Di bawah ini adalah diagram sederhana yang menjelaskan atas dasar visual.
Gambar di atas diambil oleh SBSS tim ketika saya mengambil ASP.NET MVC pelatihan di mumbai pelatihan , besar terima kasih untuk SBSS tim untuk membuat gambar di atas.
AddSingleton() menciptakan satu contoh dari layanan ketika pertama kali diminta dan reuses yang sama contoh di semua tempat di mana layanan yang dibutuhkan.
Dalam cakupan layanan dengan setiap permintaan http kita mendapatkan sebuah instance baru. Namun, di saat yang sama permintaan http jika layanan ini diperlukan di beberapa tempat seperti di lihat dan di controller kemudian contoh yang sama disediakan untuk seluruh lingkup bahwa permintaan http. Tapi baru setiap http request akan mendapatkan sebuah instance baru dari layanan.
Dengan transient layanan baru contoh yang diberikan setiap kali satu contoh layanan yang diminta apakah itu di lingkup yang sama permintaan http atau di berbagai permintaan http.
Setelah mencari jawaban untuk pertanyaan ini saya menemukan penjelasan brilian dengan contoh yang saya ingin berbagi dengan anda.
Anda dapat menonton video yang menunjukkan perbedaan [di SINI][1]
Dalam contoh ini kita memiliki kode yang diberikan:
public interface IEmployeeRepository
{
IEnumerable<Employee> GetAllEmployees();
Employee Add(Employee employee);
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MockEmployeeRepository : IEmployeeRepository
{
private List<Employee> _employeeList;
public MockEmployeeRepository()
{
_employeeList = new List<Employee>()
{
new Employee() { Id = 1, Name = "Mary" },
new Employee() { Id = 2, Name = "John" },
new Employee() { Id = 3, Name = "Sam" },
};
}
public Employee Add(Employee employee)
{
employee.Id = _employeeList.Max(e => e.Id) + 1;
_employeeList.Add(employee);
return employee;
}
public IEnumerable<Employee> GetAllEmployees()
{
return _employeeList;
}
}
HomeController
public class HomeController : Controller
{
private IEmployeeRepository _employeeRepository;
public HomeController(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}
[HttpGet]
public ViewResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create(Employee employee)
{
if (ModelState.IsValid)
{
Employee newEmployee = _employeeRepository.Add(employee);
}
return View();
}
}
Membuat View
@model Employee
@inject IEmployeeRepository empRepository
<form asp-controller="home" asp-action="create" method="post">
<div>
<label asp-for="Name"></label>
<div>
<input asp-for="Name">
</div>
</div>
<div>
<button type="submit">Create</button>
</div>
<div>
Total Employees Count = @empRepository.GetAllEmployees().Count().ToString()
</div>
</form>
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IEmployeeRepository, MockEmployeeRepository>();
}
Copy-paste kode ini dan tekan pada tombol buat di lihat dan beralih di antara
AddSingleton
, AddScoped
dan AddTransient
anda akan mendapatkan masing-masing satu kali hasil yang berbeda yang mungkin bisa membantu anda memahami penjelasan ini:
AddSingleton() - Seperti namanya, AddSingleton() metode menciptakan Singleton layanan. Singleton layanan ini dibuat saat pertama yang diminta. Ini contoh sama kemudian digunakan oleh semua berikutnya permintaan. Jadi secara umum, Singleton layanan ini dibuat hanya satu kali per aplikasi dan bahwa satu contoh adalah yang digunakan di seluruh aplikasi life time.
AddTransient() - metode Ini menciptakan Transien layanan. Baru contoh Sementara layanan ini dibuat setiap kali diminta.
AddScoped() - metode Ini menciptakan Cakupan layanan. Sebuah contoh baru dari Cakupan layanan adalah dibuat setelah per permintaan dalam lingkup. Untuk contoh, dalam aplikasi web itu menciptakan 1 contoh per masing-http permintaan tetapi menggunakan contoh yang sama dalam panggilan lain dalam waktu yang sama web permintaan.
Seperti yang dijelaskan di sini (link ini sangat berguna) dengan contoh,
pemetaan Ini antara antarmuka dan beton jenis mendefinisikan, bahwa setiap kali anda meminta jenis IContryService, anda'll mendapatkan sebuah instance baru dari CountryService. Ini adalah apa yang transien berarti dalam kasus ini. Anda juga dapat menambahkan singleton pemetaan (menggunakan AddSingleton) dan cakupan pemetaan (menggunakan AddScoped). Scoped dalam hal ini berarti cakupan untuk permintaan HTTP, yang juga berarti itu adalah singleton sementara permintaan saat ini sedang berjalan. Anda juga dapat menambahkan contoh yang ada DI wadah dengan menggunakan metode AddInstance. Ini adalah hampir lengkap cara mendaftar ke IServiceCollection