Streamlining .NET Repository Registration with Scrutor Library
Written on
Introduction to Dependency Injection and Scrutor
In ASP.NET Core development, the concept of Dependency Injection (DI) is crucial for creating loosely coupled, manageable, and testable applications. However, the manual registration of each service within the DI container can be tedious and prone to errors, especially in larger projects. This is where the Scrutor library comes in — a tool that extends the built-in service registration features of ASP.NET Core. In this article, we will delve into how Scrutor can automate the service registration process.
Understanding Scrutor
Scrutor is an open-source library designed for the .NET Core DI container. It provides a collection of extension methods that facilitate the automatic registration of services within the ASP.NET Core DI container, thus simplifying the registration process and minimizing repetitive code.
Advantages of Using Scrutor
- Less Repetitive Code: By automating service registration, Scrutor reduces the amount of boilerplate code in your application.
- Easier Maintenance: With Scrutor, adding new services doesn’t require you to remember to register them manually, simplifying ongoing maintenance.
- Versatility: Scrutor allows for flexible service registration with various lifetimes and conditions.
Configuring Scrutor in Your Project
Step 1: Install the Scrutor Package
Start by adding the Scrutor NuGet package to your project. You can accomplish this through the NuGet Package Manager or by executing the following command in the Package Manager Console:
Install-Package Scrutor
Step 2: Basic Configuration
After installation, you can configure Scrutor in your Startup.cs file. Below is a basic setup example:
public void ConfigureServices(IServiceCollection services)
{
services.Scan(scan =>
scan.FromAssemblyOf<YourAssembly>()
.AddClasses()
.AsImplementedInterfaces()
.WithTransientLifetime());
}
Advanced Features of Scrutor
While the basic configuration significantly simplifies service registration, Scrutor's true capabilities shine through its advanced features. These features provide developers with enhanced control and flexibility to tailor the service registration process according to specific needs.
#### Selecting Specific Classes
You can selectively register classes using the Where clause:
.AddClasses(classes => classes.Where(type => type.Name.EndsWith("Service")))
#### Defining Different Lifetimes
Scrutor enables you to specify various lifetimes for your services (Singleton, Scoped, or Transient):
.WithScopedLifetime()
#### Combining Filters
You can combine different filters for precise control over which services get registered:
.AddClasses(classes => classes.InNamespaces("MyApp.Services"))
.AsMatchingInterface()
Practical Application of Scrutor in a Web API 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 Scrutor is utilized for efficient repository service registration at startup. This project demonstrates how Scrutor can automatically scan and register repositories.
Without Scrutor, the registration of repositories in a .NET Core project typically involves manually adding each repository to the service collection. Here’s how that might look:
public void ConfigureServices(IServiceCollection services)
{
// Other service configurations...
// Manual registration of repositories
services.AddTransient(typeof(IGenericRepositoryAsync<>), typeof(GenericRepositoryAsync<>));
// Additional manual registrations...
}
As the number of repositories increases, this method becomes cumbersome and error-prone. By integrating Scrutor, you can replace these manual registrations with its assembly scanning feature. Here’s how:
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());
}
In this example, the services.Scan method is employed to automatically find and register all classes in the current assembly that are assignable to IGenericRepositoryAsync<>. This approach greatly streamlines the registration process and enhances code clarity.
Automatic Registration with Scrutor
What happens to the lines that registered IEmployeeRepositoryAsync, IPositionRepositoryAsync, IDepartmentRepositoryAsync, etc.? With Scrutor, these specific lines become redundant. Its assembly scanning capability automatically registers all repositories implementing IGenericRepositoryAsync<>, thus simplifying the entire process and eliminating manual code repetition.
For instance, consider IPositionRepositoryAsync, which derives from IGenericRepositoryAsync:
public interface IPositionRepositoryAsync : IGenericRepositoryAsync
{
// Define additional methods specific to Position repository
}
With Scrutor, IPositionRepositoryAsync is automatically registered based on the criteria defined in the services.Scan method. This automatic registration ensures that any new repository conforming to the same pattern will also be registered without additional manual updates.
Conclusion
Scrutor serves as a powerful open-source extension for the .NET Core DI container, offering a streamlined method for automatic service registration. This functionality reduces boilerplate code, simplifies maintenance, and provides flexibility in service registration with various lifetimes and conditions.
References
This video titled "Dependency Injection with Scrutor: Scanning and Registering" dives deeper into the practical application of Scrutor for service registration in .NET projects.