Take advantage of
Scrutor to eliminate the need for tedious boilerplate configuration to register services in ASP.Net Core.
Dependency injection (DI) facilitates loose coupling and promotes testability and maintenance. You can take advantage of dependency injection to change your implementations without having to change the classes or interfaces that leverage those implementations. Dependency injection is one of the SOLID principles of software architecture. It is used to decouple the usage of an object from the way the object is constructed.
Without dependency injection, an object has to be modified if any of its dependent objects change. If dependency injection wasn’t available, it would be very difficult to unit test objects that have dependent objects. With dependency injection, an object doesn’t construct its dependent objects internally; rather, dependent objects are injected at runtime.
Dependency injection is a first-class citizen in ASP.Net Core. However, by design, ASP.Net Core includes only a simple DI container with minimal capabilities, leaving it to third parties to extend those capabilities. Scrutoris an open source library that adds assembly scanning capabilities to the ASP.Net Core DI container. This article examines how we can work with Scrutor in ASP.Net Core.
It’s important to note that Scrutor is not a DI container. Rather, Scrutor provides a fluent API to register services based on conventions, using the built-in DI container of ASP.Net Core. If you need a DI container with more features and capabilities, you can use third-party DI containers such as AutoFac, Windsor, StructureMap, Ninject, and DryIoc. Scrutor can be used to provide assembly scanning and decoration extensions in ASP.Net Core.
Create an ASP.Net Core Web API project
In this section we will create an ASP.Net Core application and use it to learn how we can work with the Scrutor. Follow the steps outlined below to create a new ASP.Net Core project in Visual Studio 2017.
- Launch the Visual Studio 2017 IDE.
- Click File > New > Project.
- Select the “ASP.Net Core Web Application” project template.
- Specify the name and location for your project.
- Click OK.
- In the “New ASP.Net Core Web Application” dialog window, select .Net Core.
- Select ASP.Net Core 2.1 as the project’s version.
- Select “Web API” as the project template.
- Uncheck the “Enable Docker Support” and “Configure for HTTPS” check boxes; we won’t be using those features here.
- Ensure that the message “No Authentication” is displayed; we won’t be needing authentication either.
- Click OK.
This will create a new ASP.Net Core project in Visual Studio. Next, install Scrutor from NuGet using the NuGet Package Manager or the NuGet Console. As of this writing, the latest version of Scrutor is 3.0.2.
Scanning assemblies using Scrutor in ASP.Net Core
The Scrutor API has two extension methods—scan and decorate—that extend the functionality of the IServiceCollection interface. While scan is used to search an assembly for types that correspond to a service to be registered, decorate is used to decorate an instance of a service. In this post we will be examining the scan method. I’ll describe how we can use the decorate method in a later post here.
When using the scan method, you define a selector, a registration strategy, the services, and the lifetime of the services. The selector is used to specify how the services can be located in an assembly. Scrutor scans the types in an assembly, searching for one that matches the convention, and then registers it with the built-in DI container of ASP.Net Core.
Let’s understand this with an example. Assume that you have to register three services—namely, IService1, IService2, and IService3. Let the corresponding service implementations be in classes named Service1, Service2, and Service3. Without Scrutor, the code you would typically need to write to register these services would look as follows.
Registering services using Scrutor in ASP.Net Core
The following code snippet illustrates how you can register these services in the ConfigureServices method of the Startup class in a much simplified manner by leveraging the assembly scanning capabilities of Scrutor.
public void ConfigureServices(IServiceCollection services)
You can also specify the types explicitly in the scan method. Suppose you have two services, ServiceA and ServiceB. The following code snippet illustrates how you would register these services as transient services.
The following code snippet illustrates how you can mention the types explicitly in the scan method and register these two services with a transient lifetime.
services.Scan(scan => scan
In another variation of the scan method, you can explicitly pass the type and have Scrutor find all classes in the assembly of that type. Here is an example that illustrates this.
services.Scan(scan => scan
Scrutor is an open source framework that adds scanning capabilities to the default Microsoft.Extensions.DependencyInjection DI container in ASP.Net Core. It can also provide service decoration capabilities.