Tính năng chèn phụ thuộc trong C# là cứu cánh khi tổ chức các phần phụ thuộc - đặc biệt là trong các ứng dụng ASP.NET Core phức tạp hơn. Và nếu bạn đã quen thuộc với IServiceCollection hoặc chỉ muốn bám sát nhất có thể các dịch vụ DI đã được cung cấp, thì Scrutor trong C# là một cải tiến tuyệt vời.
Trong bài viết này, tôi sẽ cung cấp cho bạn cái nhìn tổng quan cấp cao về Dependency Insert và Scrutor trong C#. Nhưng từ đó, chúng ta sẽ đề cập ngay đến 3 mẹo mà bạn có thể sử dụng với Scrutor và chúng có thể rất hữu ích cho ứng dụng của bạn!
Scrutor là gói NuGet mạnh mẽ trong C# giúp tăng cường khả năng chèn phụ thuộc. Nó đơn giản hóa việc đăng ký và giải quyết các phần phụ thuộc, giúp bạn quản lý và sắp xếp mã của mình dễ dàng hơn.
Tính năng chèn phụ thuộc là một cách tiếp cận phổ biến để định cấu hình các ứng dụng nhằm thúc đẩy sự ghép nối lỏng lẻo và cải thiện khả năng kiểm tra cũng như khả năng bảo trì. Nó liên quan đến việc đưa các phần phụ thuộc vào một lớp thay vì trực tiếp tạo chúng trong lớp đó. Điều này có nghĩa là trách nhiệm tạo ra phần phụ thuộc không thuộc về lớp yêu cầu nó mà thay vào đó, thuộc sở hữu của ai đó ở cấp cao hơn trong ngăn xếp cuộc gọi. Cuối cùng, điều này đẩy gần như tất cả việc tạo phần phụ thuộc đến điểm đầu vào của ứng dụng, khiến ứng dụng trở nên khó sử dụng. Tuy nhiên, các khung chèn phụ thuộc giúp dọn dẹp và sắp xếp tất cả logic này .
Scrutor đưa khái niệm này tiến thêm một bước bằng cách cung cấp một cách đơn giản và trực quan để đăng ký và giải quyết các phần phụ thuộc. Với Scrutor, bạn không cần phải đăng ký thủ công từng phần phụ thuộc một nữa. Thay vào đó, bạn có thể sử dụng các quy ước và thuộc tính để tự động hóa quy trình.
Để minh họa cách sử dụng Scrutor trong C# để đăng ký và giải quyết, hãy xem xét một tình huống đơn giản. Hãy tưởng tượng chúng ta có một ứng dụng yêu cầu sử dụng các kho dữ liệu khác nhau, chẳng hạn như UserRepository và ProductRepostiory.
Đầu tiên, chúng ta cần cài đặt gói Scrutor NuGet trong dự án của mình. Mở Bảng điều khiển quản lý gói và chạy lệnh sau:
Install-Package Scrutor
Tiếp theo, chúng ta cần xác định kho lưu trữ và giao diện tương ứng của chúng. Ví dụ này về cơ bản là trống, nhưng lát nữa chúng ta sẽ đề cập đến những ví dụ này:
public interface IUserRepository { // Interface methods } public class UserRepository : IUserRepository { // Implementation } public interface IProductRepository { // Interface methods } public class ProductRepository : IProductRepository { // Implementation }
Bây giờ, hãy kết nối các phần phụ thuộc của chúng ta bằng Scrutor. Trong mã khởi động của bạn (chẳng hạn như trong phương thức configureServices trong ASP.NET Core), hãy thêm mã sau:
services.Scan(scan => scan .FromAssemblyOf<Startup>() .AddClasses(classes => classes.AssignableToAny( typeof(IUserRepository), typeof(IProductRepository))) .AsImplementedInterfaces() .WithScopedLifetime());
Mã này sử dụng phương thức Quét từ Scrutor để quét cụm có chứa lớp Khởi động. Sau đó, nó lọc ra các lớp có thể gán cho giao diện IUserRepository hoặc IProductRepository. Cuối cùng, nó ánh xạ việc triển khai các giao diện này và đăng ký chúng với các giao diện tương ứng.
Bây giờ, chúng ta có thể đưa những phần phụ thuộc này vào các lớp của mình. Ví dụ: giả sử chúng ta có lớp UserService yêu cầu IUserRepository:
public class UserService { private readonly IUserRepository _userRepository; public UserService(IUserRepository userRepository) { _userRepository = userRepository; } // Rest of the class implementation }
Bằng cách khai báo IUserRepository là phần phụ thuộc trong hàm tạo, Scrutor cùng với IServiceCollection sẽ tự động giải quyết và đưa phiên bản UserRepository vào cho chúng ta.
Hãy tưởng tượng bạn có giao diện dịch vụ IService
và triển khai MyService
. Bạn muốn ghi nhật ký mục nhập và thoát của từng lệnh gọi phương thức trong MyService
mà không làm ảnh hưởng đến logic nghiệp vụ của nó do các mối lo ngại về ghi nhật ký.
Đầu tiên, xác định giao diện IService
và cách triển khai nó:
public interface IService { void DoWork(); } public class MyService : IService { public void DoWork() { // Business logic here } }
Tiếp theo, tạo một lớp trang trí LoggingDecorator
triển khai IService
. Lớp này sẽ bao bọc dịch vụ thực tế và thêm tính năng ghi nhật ký xung quanh các lệnh gọi phương thức được ủy quyền:
public class LoggingDecorator : IService { private readonly IService _decorated; private readonly ILogger<LoggingDecorator> _logger; public LoggingDecorator(IService decorated, ILogger<LoggingDecorator> logger) { _decorated = decorated; _logger = logger; } public void DoWork() { _logger.LogInformation("Starting work."); _decorated.DoWork(); _logger.LogInformation("Finished work."); } }
Bây giờ, hãy sử dụng Scrutor để đăng ký dịch vụ của bạn và trình trang trí của nó trong Startup.cs
hoặc bất cứ nơi nào bạn định cấu hình dịch vụ của mình:
public void ConfigureServices(IServiceCollection services) { // Register the base service services.AddScoped<IService, MyService>(); // Use Scrutor to apply the decorator services.Decorate<IService, LoggingDecorator>(); // Make sure to register the ILogger or ILogger<T> dependencies if not already done }
Thiết lập này sử dụng Scrutor để gói đăng ký IService
bằng LoggingDecorator
. Khi phân giải IService
, vùng chứa DI sẽ cung cấp một phiên bản LoggingDecorator
, phiên bản này sẽ bao bọc một phiên bản MyService
. Cách tiếp cận này đạt được sự phân tách các mối quan tâm bằng cách giữ logic ghi nhật ký bên ngoài logic nghiệp vụ của bạn.
Khi chúng tôi xây dựng các hệ thống phức tạp, thường có trường hợp chúng tôi muốn giới thiệu thứ gì đó như cờ tính năng. Điều này cho phép chúng tôi sử dụng các đường dẫn mã khác nhau dựa trên cấu hình và không phải biên dịch lại và triển khai toàn bộ ứng dụng. Trong một số trường hợp, vấn đề không chỉ là chọn một đường dẫn mã khác mà còn là việc hoán đổi toàn bộ quá trình triển khai một thứ gì đó!
Chúng ta hãy cùng nhau thử một ví dụ! Giả sử bạn có giao diện IFeatureService
với nhiều cách triển khai: NewFeatureService
(một tính năng mới, thử nghiệm) và StandardFeatureService
(tính năng hiện tại, ổn định). Bạn muốn chuyển đổi giữa các triển khai này trong thời gian chạy dựa trên cờ cấu hình.
Đầu tiên, xác định giao diện IFeatureService
và cách triển khai nó:
public interface IFeatureService { void ExecuteFeature(); } public class NewFeatureService : IFeatureService { public void ExecuteFeature() { // New feature logic } } public class StandardFeatureService : IFeatureService { public void ExecuteFeature() { // Standard feature logic } }
Tiếp theo, bạn cần một cách để xác định cách triển khai nào sẽ sử dụng dựa trên cài đặt chuyển đổi tính năng. Đây có thể là một giá trị trong appsettings.json
, cài đặt cơ sở dữ liệu hoặc bất kỳ nguồn cấu hình nào khác.
Bây giờ, hãy sử dụng Scrutor để đăng ký động việc triển khai dịch vụ phù hợp dựa trên chuyển đổi tính năng:
public void ConfigureServices(IServiceCollection services) { // Assume GetFeatureToggleValue() retrieves the current feature toggle setting var useNewFeature = GetFeatureToggleValue("UseNewFeature"); // Dynamically register the appropriate implementation based on the feature toggle if (useNewFeature) { services.AddScoped<IFeatureService, NewFeatureService>(); } else { services.AddScoped<IFeatureService, StandardFeatureService>(); } // Optional: You could combine this with the previous example // to use the decorator pattern too! // services.Decorate<IFeatureService, FeatureServiceProxy>(); } private bool GetFeatureToggleValue(string featureName) { // This method would typically check your // configuration source to determine if the feature is enabled // For simplicity, this is just a placeholder return false; // or true based on actual configuration }
Áp dụng cách tiếp cận như thế này có thể giúp chúng ta:
Trong bài viết này, tôi đã cung cấp cho bạn 3 mẹo đơn giản để chèn phần phụ thuộc bằng Scrutor trong C#. Sau phần tổng quan ngắn gọn về nội dung phụ thuộc là gì và cách Scrutor phù hợp với nó, chúng tôi đã đi ngay vào các ví dụ của mình. Chúng ta phải xem quá trình quét tập hợp, cách trang trí các phần phụ thuộc và thậm chí cả cách xem xét tính năng gắn cờ cho toàn bộ quá trình triển khai!
Tính năng chèn phụ thuộc là thứ có thể đơn giản hóa đáng kể các ứng dụng của bạn khi chúng ngày càng phức tạp và Scrutor có thể trợ giúp rất nhiều nếu bạn muốn sử dụng dịch vụ IServiceCollection tích hợp sẵn từ Microsoft . Nếu bạn thấy điều này hữu ích và bạn đang tìm kiếm thêm cơ hội học tập, hãy cân nhắc đăng ký nhận bản tin kỹ thuật phần mềm miễn phí hàng tuần của tôi và xem các video miễn phí của tôi trên YouTube ! Hãy tham gia cùng tôi và các thành viên cộng đồng khác trên Discord !
Cũng được xuất bản ở đây.