Chuyển đến nội dung chính

Dependency injection trong .NET Core

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.
Chúng ta sẽ làm 1 ví dụ để hiểu rõ thêm về cách hoạt động của 3 hàm đăng ký trên.
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.
Hi vọng với ví dụ nhỏ này, mọi người sẽ chọn cách đăng ký DI sao cho phù hợp với dự án.
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

Nhận xét

Đăng nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.