Angular 17 and NET Core 8: Simplifying Repository Registration with Scrutor Library
Appendix C
Preface
This is another installment in our comprehensive series, Building a Talent Management SPA with Angular 17 and NET Core 8. For a broader view of the series and to access other parts, you can refer back to the series’ table of contents, where each segment is meticulously organized to guide you through every stage of building a robust Talent Management SPA.
Introduction
This is Appendix C in our comprehensive series “Building a Talent Management SPA with Angular 17 and .NET Core 8”. In this appendix, we dive into the Nugget package Scutor to automate and simplify repository registration for dependency injection.
In ASP.NET Core development, Dependency Injection (DI) is a fundamental concept that helps in achieving loosely coupled, manageable, and testable code. However, manually registering each service with the DI container can be tedious and error-prone, especially in larger projects. This is where Scrutor comes into play — a library that enhances the built-in service registration capabilities of ASP.NET Core. In this blog, we’ll explore how to use Scrutor to automate the process of registering your services.
Content
In this blog, I will introduce you to NuGet library Scutor and provide examples of its usage within the Web API project. This blog is a supplement to the ‘Building a Talent Management SPA with Angular 17 and .NET Core 8 Tutorial Series’.
Part 1: What is Scrutor?
Scrutor is an open-source extension library for the .NET Core DI container. It provides a set of extension methods to automatically register your services with the ASP.NET Core DI container, simplifying the registration process and reducing boilerplate code.
1.1 Benefits of Using Scrutor
- Reduced Boilerplate: Automatically registering services reduces the amount of repetitive code in your project.
- Ease of Maintenance: With Scrutor, adding a new service doesn’t require you to remember to register it manually (yeah!!!), making maintenance easier.
- Flexibility: Scrutor offers a flexible way to register services with various lifetimes and conditions.
1.2 Setting Up Scrutor in Your Project
Step 1: Install the Package: Begin by installing the Scrutor NuGet package. You can do this via the NuGet Package Manager or by running the following command in the Package Manager Console:
Install-Package ScrutorStep 2: Basic Configuration
Once installed, you can start configuring Scrutor in your Program.cs file. Here’s a basic setup:
public void ConfigureServices(IServiceCollection services)
{
services.Scan(scan =>
scan.FromAssemblyOf<SomeType>()
.AddClasses()
.AsImplementedInterfaces()
.WithTransientLifetime());
}1.3 Advanced Usages
While the basic setup of Scrutor greatly simplifies service registration, its true power lies in its advanced features. These features offer enhanced control and flexibility, allowing developers to tailor the service registration process to their specific needs.
In this section, we’ll explore some of these advanced usages of Scrutor, such as selecting specific classes, setting different lifetimes for services, and combining various filters to fine-tune the registration process. These techniques enable more sophisticated and efficient configurations, ensuring that your ASP.NET Core application is optimized for performance and maintainability.
Selecting Specific Classes
You can use Where clause to selectively register classes:
.AddClasses(classes => classes.Where(type => type.Name.EndsWith("Service")))Setting Different Lifetimes
Scrutor allows you to specify different lifetimes for your services (Singleton, Scoped, or Transient):
.WithScopedLifetime()Combining Filters
Combine different filters for precise control over which services are registered:
.AddClasses(classes => classes.InNamespaces("MyApp.Services"))
.AsMatchingInterface()Part 2 — Practical Example of Scrutor within a WebAPI Project
In the Building a Talent Management SPA with Angular 17 and NET Core 8 Tutorial Series, I have included a sample Web API project where I leverage Scrutor for efficient registering repository services at project startup. This project showcases how Scrutor is utilized to automatically scan and register repositories. Let’s delve into the implementation details.
Without Scrutor, repository registration in a .NET Core project typically involves manually adding each repository to the service collection. This is done within the service registration section within Program.cs. Here’s an example of what that might look like:
public void ConfigureServices(IServiceCollection services)
{
// Other service configurations...
// Manual registration of repositories
services.AddTransient(typeof(IGenericRepositoryAsync<>), typeof(GenericRepositoryAsync<>));
services.AddTransient<IPositionRepositoryAsync, PositionRepositoryAsync>();
services.AddTransient<IEmployeeRepositoryAsync, EmployeeRepositoryAsync>();
services.AddTransient<IDepartmentRepositoryAsync, DepartmentRepositoryAsync>();
services.AddTransient<ISalaryRangeRepositoryAsync, SalaryRangeRepositoryAsync>();
// Additional configurations...
}In the above code, each repository is individually registered with the dependency injection container. As the number of repositories grows, this approach becomes more cumbersome and prone to errors.
After integrating Scrutor, you can replace the manual repository registrations with Scrutor’s assembly scanning functionality. Here’s how you can do it:
public void ConfigureServices(IServiceCollection services)
{
// Other service configurations...
// Using Scrutor to register repositories
services.Scan(scan => scan
.FromCallingAssembly()
.AddClasses(classes => classes.AssignableTo(typeof(IGenericRepositoryAsync<>)))
.AsImplementedInterfaces()
.WithTransientLifetime());
// Additional configurations...
}In this example, Scutor services.Scan is used to automatically find and register all classes in the calling assembly that are assignable to IGenericRepositoryAsync<>. This greatly simplifies the registration process and makes your code cleaner and more maintainable.
Wait a minute! What about the lines that registered IEmployeeRepositoryAsync, IPositionRepositoryAsync, IDepartmentRepositoryAsync, ISalaryRangeRepositoryAsync, etc.? With the integration of Scrutor, these specific lines of registration become unnecessary. Scrutor's assembly scanning feature automatically registers all repositories that implement IGenericRepositoryAsync<>, including those mentioned, streamlining the entire process and reducing manual code redundancy.
Let’s consider IPositionRepositoryAsync as a specific example. This interface inherits from IGenericRepositoryAsync<Position>:
public interface IPositionRepositoryAsync : IGenericRepositoryAsync<Position>
{
// Define additional methods specific to Position repository
}With Scrutor, IPositionRepositoryAsync gets automatically registered without needing explicit code, as it matches the criteria defined in the services.Scan method. This automatic handling by Scrutor ensures that any new repository following the same pattern will also be automatically registered, reducing the need for manual updates in the service configuration.
Want to try out the .NET 6 Web API project with Scrutor in action? Check it out here: https://github.com/workcontrolgit/TalentManagementApi.
Summary
Scrutor is presented as an open-source extension library for the .NET Core DI container. It offers a streamlined approach to automatically register services, thereby reducing boilerplate code, simplifying maintenance, and providing flexibility in service registration with various lifetimes and conditions.
References
- For more information on the Scrutor project, visit its GitHub repository: https://github.com/khellang/Scrutor
Thanks for reading! Hope you found it useful. Want more? Please follow me on medium for more articles. With your support, I’ll keep creating awesome content for you. Have a great day ahead! — Fuji Nguyen




