Asp.net Core
tích hợp sẵn một DI Container để đăng ký và sử dụng các dịch vụ với kỹ thuật DI,
Đối tượng này thuộc kiểu IServiceCollection
mà đã tìm hiểu ở mục
Sử dụng ServiceCollection.
Phần này sẽ sử dụng IServiceCollection tích hợp sẵn trong ASP.NET CORE
Tạo ra dự án mẫu, tạo thư mục chứa code dự án 04.ServiceCollection
vào thư mục đó gõ lệnh
dotnet new web
Sau đó mở ra bằng VSC, trong ví dụ trước (ASP.NET Core) Đọc và ghi Request và Response, đã tạo ra một lớp tĩnh tiện ích là HtmlHelper để phát sinh mã HTML nhanh hơn, hãy lấy file nguồn về và đưa vào dự án để sử dụng ngay, file nguồn HtmlHelper.cs
Đồng thời bạn cũng tích hợp thư viện CSS Bootstrap vào theo hướng dẫn tại:
Webpack đóng gói CSS, JS với ASP.NET Core
,
sau đó cũng thiết lập sử dụng truy cập file tĩnh app.UseStaticFiles();
- Tạo dịch vụ để thực hành
- Đăng ký dịch vụ cho ứng dụng Asp.net Core
- Inject dịch vụ vào đối tượng sử dụng
- Map, MapWhen và sử dụng dịch vụ
- Các dịch vụ đã đăng ký
Tạo các lớp dịch vụ để thực hành
Định nghĩa interface có tên IListProductName
,
có phương thức để lấy danh sách chuỗi - tên các sản phẩm.
using System.Collections.Generic; using System.Collections; public interface IListProductName { // Trả về danh sách các tên IEnumerable<string> GetNames(); }
Triển khai giao diện IListProductName với hai lớp dịch vụ gồm LaptopName
và PhoneName
using System.Collections.Generic; using System.Collections; public class LaptopName : IListProductName { public LaptopName() => System.Console.WriteLine("LaptopName Created"); // Mảng tên sản phẩm string[] laptops = new string[] { "Apple MacBook Pro 13 inch", "HP Spectre X360", "Samsung Chromebook Pro"}; public IEnumerable<string> GetNames() { return laptops; } }Services/PhoneName.cs
using System.Collections.Generic; using System.Collections; public class PhoneName : IListProductName { public PhoneName() => System.Console.WriteLine("PhoneName created"); // Mảng tên các điện thoại private List<string> phone_names = new List<string> { "Iphone 7", "Samsung Galaxy", "Nokia 123" }; public IEnumerable<string> GetNames() { return phone_names; } }
Đăng ký dịch vụ cho ứng dụng ASP.NET Core
Ứng dụng ASP.NET Core cung cấp sẵn một DI Container có kiểu IServiceCollection
, đối tượng này để đăng ký
các dịch vụ vào ứng dụng. Các đăng ký sẽ thực hiện ở phương thức ConfigureServices
của lớp Startup
Vậy hãy cập nhật phương thức đó - đăng ký dịch vụ như sau:
/.. public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IListProductName, PhoneName>(); // đăng ký dịch vụ, đối tượng chỉ tạo một lần services.AddTransient<LaptopName, LaptopName>(); // đăng ký dịch vụ, tạo mới mỗi lần triệu gọi } /..
Như vậy đã đăng ký được dịch vụ vào ứng dụng, để triệu gọi ra các dịch vụ này trực tiếp thì sử dụng đối tượng kiểu
IApplicationBuilder
có trong phương thức Configure
của lớp Startup
,
ví dụ:
/.. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { /.. var myservice = app.ApplicationServices.GetService<IListProductName>(); /.. } /..
Hoặc có thể lấy thông qua HttpContext
var myservice = context.RequestServices.GetService<IListProductName>();
Inject các dịch vụ
Các đối dịch vụ đăng ký vào ứng dụng, được Inject vào các dịch vụ khác khi cần thiết, ví dụ sau -
tạo ra lớp có tên ProductController
sử dụng dịch vụ IListProductName
và LaptopName
,
hai dịch vụ này Inject vào ProductController
qua phương thức khởi tạo của nó.
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using System.Text; using System.Linq; namespace _04.ServiceCollection { public class ProductController { IListProductName lsPhone; IListProductName lsLaptop; // Inject hai dịch vụ qua phương thức khởi tạo public ProductController(IListProductName lsphone, LaptopName lslaptop) { Console.WriteLine(this.GetType().Name + " created"); this.lsPhone = lsphone; this.lsLaptop = lslaptop; } // Xuất danh sách sản phẩm cho Response public async Task List(HttpContext context) { var sb = new StringBuilder(); string lsPhoneHTML = string.Join("", lsPhone.GetNames().Select(name => name.HtmlTag("li"))).HtmlTag("ul"); string lsLaptopHTML = string.Join("", lsLaptop.GetNames().Select(name => name.HtmlTag("li"))).HtmlTag("ul"); sb.Append("Danh sách điện thoại".HtmlTag("h2")); sb.Append(lsPhoneHTML); sb.Append("Danh sách Laptop".HtmlTag("h2")); sb.Append(lsLaptopHTML); string menu = HtmlHelper.MenuTop(HtmlHelper.DefaultMenuTopItems(), context.Request); string html = HtmlHelper.HtmlDocument("DS Sản phẩm", menu + sb.ToString().HtmlTag("div", "container")); context.Response.StatusCode = 200; await context.Response.WriteAsync(html); } } }
Tiếp tục đăng ký ProductController
như là dịch vụ của ứng dụng
/.. public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IListProductName, PhoneName>(); services.AddTransient<LaptopName, LaptopName>(); services.AddTransient<ProductController, ProductController>(); } /..
Với cách đăng ký dịch vụ như vậy, khi lấy ra dịch vụ ProductController
thì dịch vụ IListProductName
và LaptopName
đã tự động Inject vào nó.
Map, MapWhen và sử dụng dịch vụ
Phương thức Map
thuộc lớp IApplicationBuilder
để routing Url một cách đơn giản - nó
tạo ra một điểm rẽ nhánh trên pipeline.
Bài trước đã trình bày về nó: xem tại
IApplicationBuilder Map
Ví dụ, tạo ra điểm rẽ nhánh trên pipeline khi truy vấn với Url là /Product
app.Map("/Product", app => { app.Run(async (context) => { // Gọi đến dịch vụ ProductController var productcontroller = app.ApplicationServices.GetService<ProductController>(); await productcontroller.List(context); }); });
MapWhen
Ý nghĩa của MapWhen giống Map, tạo ra một điểm rẽ nhánh trên pipeline - điểm khác là MapWhen không trực tiếp tạo mẫu route để so sánh với Url gửi đến rồi rẽ nhánh mà MapWhen lại thực hiện với một điều kiện logic bất kỳ nào đó. Cú pháp là:
MapWhen(Func<HttpContext, bool> predicate, Action<IApplicationBuilder> configuration);
Nếu predicate trả về true thì thực hiện configuration (trong nó thường tạo điểm cuối với RequestDelegate). Về Func và Action thì xem chi tiết tại: Delegate Func và Action
Ví dụ, thực hiện điều hướng Request - nếu url truy vấn (path) bắt đầu bởi Abcxyz
app.MapWhen( (context) => { return context.Request.Path.Value.StartsWith("/Abcxyz"); }, appProduct => { appProduct.Run(async (context) => { await appProduct.ApplicationServices.GetService<ProductController>().List(context); }); });
Như vậy có thể truy cập với địa chỉ http://localhost:5000/Abcxyz123
,
http://localhost:5000/Abcxyz
...
Kiểm tra các dịch vụ đã đăng ký
Một ứng dụng ASP.NET có nhiều dịch vụ đăng ký vào DI Container, để xem ứng dụng đang có dịch vụ nào chúng ta liệt kê hết ra bằng cách sau:
public class Startup { IServiceCollection _services; public void ConfigureServices(IServiceCollection services) { /.. _services = services; } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { /.. app.Map("/allservice", app01 => { app01.Run(async (context) => { var stringBuilder = new StringBuilder(); stringBuilder.Append("<tr><th>Tên</th><th>Lifetime</th><th>Tên đầy đủ</th></tr>"); foreach (var service in _services) { string tr = service.ServiceType.Name.ToString().HtmlTag("td") + service.Lifetime.ToString().HtmlTag("td") + service.ServiceType.FullName.HtmlTag("td"); stringBuilder.Append(tr.HtmlTag("tr")); } string htmlallservice = stringBuilder.ToString().HtmlTag("table", "table table-bordered table-sm"); string html = HtmlHelper.HtmlDocument("Các dịch vụ", (htmlallservice)); await context.Response.WriteAsync(html); }); }); /.. } }
Tham khảo mã nguồn hoặc tải về