Depedency Injection là gì?
Dependency Injection (DI) là 1 kỹ thuật để chống lại sự phụ thuộc giữa các đối tượng, các thành phần, và các lớp bằng cách nghịch đảo luồng điểu khiển của ứng dụng.Có 3 khái niệm Dependency Injection: Constructor injection, Setter Injection, và Interface Injection.
Trong bài viết này, chúng ta chỉ làm ví dụ về Constructor injection.
Định nghĩa trên trang Asp.net:
Dependency injection (DI) is a technique for achieving loose coupling between objects and their collaborators, or dependencies. Rather than directly instantiating collaborators, or using static references, the objects a class needs in order to perform its actions are provided to the class in some fashion. Most often, classes will declare their dependencies via their constructor, allowing them to follow the Explicit Dependencies Principle. This approach is known as "constructor injection".Ngoài ra, các bạn có thể tham khảo thêm ở trang: https://www.martinfowler.com/articles/injection.html của bác Martin.
Dependency Injection là 1 trong 5 khái niệm quan trọng trong nguyên lý thiết kế hướng đối tượng.
Trước đây, khi .NET Core chưa ra đời, bạn phải sử dụng thư viện bên ngoài như Autofac, Ninject, Structure Map, … Từ phiên bản .NET Core trở đi, Microsoft đã hỗ trợ Dependency Injection.
Để sử dụng DI, bạn cần định nghĩa các service muốn sử dụng trong hàm ConfigureServices() trong class Startup.cs.
Khai báo DI trong .NET Core
Có 3 loại Lifetime trong .NET Core:- Transient: đối tượng sẽ được khởi tạo ra mỗi lần khi có yêu cầu.
- Scoped: đối tượng được tạo ra khi có yêu cầu cho mỗi request.
- Singleton: đối tượng được tạo ra cho lần request đầu tiên. Sau đó các request tiếp theo, sẽ trả về cùng 1 đối tượng.
Khai báo 4 interface, và đăng ký DI trong file Startup.cs:
- IOperationTransient: đăng ký DI bằng hàm Transient
- IOperationScoped: đăng ký DI bằng hàm Scope
- IOperationSingleton: đăng ký DI bằng hàm Singleton
- IOperationSingletonInstance: đăng ký DI bằng hàm Singleton với param Guid empty.
public interface IOperation
{
Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}
Đăng ký DI
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
// Add framework services.
services.AddMvc();
}
Khai báo class Operation kế thừa từ 4 interface trên. Mỗi lần 1 object được tạo ra, mình sẽ gán 1 mã Guid vào đối tượng đó.
public class Operation : IOperationTransient,
IOperationScoped,
IOperationSingleton,
IOperationSingletonInstance
{
public Operation() : this(Guid.NewGuid())
{
}
public Operation(Guid id)
{
OperationId = id;
}
public Guid OperationId { get; private set; }
}
Chúng ta sẽ sử dụng DI trong Controller và OperationService:
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()
{
var operationDisplayModel = new OperationDisplayModel
{
TransientOperation = _transientOperation,
ScopedOperation = _scopedOperation,
SingletonOperation = _singletonOperation,
SingletonInstanceOperation = _singletonInstanceOperation,
ServiceOperation = _operationService
};
return View(operationDisplayModel);
}
}
File OperationService:
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;
}
}
Kết quả lần request thứ nhất:Kết quả lần request thứ hai:
Quan sát giá trị OperationID trong 1 lần request, và kết quả giữa lần request 1 và 2:
- Transient: Đối tượng luôn được tạo mới khi có request từ Controller và từ Service.
- Scoped: sử dụng cùng 1 đối tượng trong 1 request, nhưng khác nhau giữa các lần request.
- Singleton: luôn sử dụng cùng 1 đối tượng.
Link download: MediaFire
Tham khảo:
Nguyên lý thiết kế hướng đối tượng: http://deviq.com/solid/Dependency Injection: https://en.wikipedia.org/wiki/Dependency_injection
Depedency Injection in ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#registering-your-own-services
Chúc các bạn thành công!
Nhatkyhoctap's blog
bài viết quá hay :)
Trả lờiXóa