Tận dụng lợi thế của Scrutor để loại bỏ cấu hình boilerplate không cần thiết để đăng ký dịch vụ trong ASP.Net Core
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. Scrutor is 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.
1 2 3 |
<span class="pln">services</span><span class="pun">.</span><span class="typ">AddScoped</span><span class="pun"><</span><span class="typ">IService1</span><span class="pun">,</span> <span class="typ">Service1</span><span class="pun">>();</span> <span class="pln">services</span><span class="pun">.</span><span class="typ">AddScoped</span><span class="pun"><</span><span class="typ">IService2</span><span class="pun">,</span> <span class="typ">Service2</span><span class="pun">>();</span> <span class="pln">services</span><span class="pun">.</span><span class="typ">AddScoped</span><span class="pun"><</span><span class="typ">IService3</span><span class="pun">,</span> <span class="typ">Service3</span><span class="pun">>();</span> |
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.
1 2 3 4 5 6 7 8 |
<span class="kwd">public</span> <span class="kwd">void</span> <span class="typ">ConfigureServices</span><span class="pun">(</span><span class="typ">IServiceCollection</span><span class="pln"> services</span><span class="pun">)</span> <span class="pln"> </span><span class="pun">{</span> <span class="pln"> services</span><span class="pun">.</span><span class="typ">Scan</span><span class="pun">(</span><span class="pln">scan </span><span class="pun">=></span> <span class="pln"> scan</span><span class="pun">.</span><span class="typ">FromCallingAssembly</span><span class="pun">()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">AddClasses</span><span class="pun">()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">AsMatchingInterface</span><span class="pun">());</span> <span class="pln"> services</span><span class="pun">.</span><span class="typ">AddMvc</span><span class="pun">().</span><span class="typ">SetCompatibilityVersion</span><span class="pun">(</span><span class="typ">CompatibilityVersion</span><span class="pun">.</span><span class="typ">Version_2_1</span><span class="pun">);</span> <span class="pln"> </span><span class="pun">}</span> |
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.
1 2 |
<span class="pln">services</span><span class="pun">.</span><span class="typ">AddTransient</span><span class="pun"><</span><span class="typ">ServiceA</span><span class="pun">>();</span> <span class="pln">services</span><span class="pun">.</span><span class="typ">AddTransient</span><span class="pun"><</span><span class="typ">ServiceB</span><span class="pun">>();</span> |
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.
1 2 3 4 |
<span class="pln">services</span><span class="pun">.</span><span class="typ">Scan</span><span class="pun">(</span><span class="pln">scan </span><span class="pun">=></span><span class="pln"> scan</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">AddTypes</span><span class="pun"><</span><span class="typ">ServiceA</span><span class="pun">,</span> <span class="typ">ServiceB</span><span class="pun">>()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">AsSelf</span><span class="pun">()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">WithTransientLifetime</span><span class="pun">());</span> |
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.
1 2 3 4 5 |
<span class="pln">services</span><span class="pun">.</span><span class="typ">Scan</span><span class="pun">(</span><span class="pln">scan </span><span class="pun">=></span><span class="pln"> scan</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">FromAssemblyOf</span><span class="pun"><</span><span class="typ">IDataService</span><span class="pun">>()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">AddClasses</span><span class="pun">()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">AsSelf</span><span class="pun">()</span> <span class="pln"> </span><span class="pun">.</span><span class="typ">WithTransientLifetime</span><span class="pun">());</span> |
Scrutor là một framework nguồn mở bổ sung khả năng quét vào các container mặc định Microsoft.Extensions.DependencyInjection DI trong ASP.Net Core. Nó cũng có thể cho phép service decoration. Tôi sẽ thảo luận về việc sử dụng Scrutor để trang trí dịch vụ trong một bài sau ở đây.
Bài viết của Joydip Kanjilal – một Microsoft MVP (Most Valuable Professional) về ASP.Net, đồng thời cũng là nhà diễn giả và là tác giả của nhiều cuốn sách, báo với hơn 16 năm kinh nghiệm trong lĩnh vực IT.