导读:本期聚焦于小伙伴创作的《C#如何批量扫描和注册服务?Scrutor自动注册依赖方法详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何批量扫描和注册服务?Scrutor自动注册依赖方法详解》有用,将其分享出去将是对创作者最好的鼓励。

在C#的.NET应用开发中,依赖注入是构建松耦合系统的核心机制,常规的服务注册需要手动为每个实现类指定对应的服务类型和生命周期,当项目中的服务数量达到数十甚至上百个时,这种逐个注册的方式会显得非常低效,还容易出现注册遗漏的问题。Scrutor是一个专门优化依赖注入注册流程的第三方库,它支持通过配置规则批量扫描程序集,自动完成服务的匹配和注册,能够很好地解决手动注册的痛点。

C#如何批量扫描和注册服务?Scrutor自动注册依赖方法详解

Scrutor基础介绍

Scrutor是基于Microsoft.Extensions.DependencyInjection扩展的轻量级库,它的核心能力是提供IServiceCollection的扩展方法,让开发者可以通过扫描指定程序集,按照自定义规则批量注册服务。它不会替换原有的依赖注入容器,只是在原有基础上增加了批量注册的能力,因此和现有的依赖注入用法完全兼容。

使用前需要先通过NuGet安装Scrutor包,安装命令如下:

dotnet add package Scrutor

基础批量注册示例

假设我们有如下的服务接口和实现类,分布在同一个程序集中:

// 服务接口
public interface IUserService
{
    string GetUserName(int id);
}

public interface IOrderService
{
    string GetOrderInfo(int orderId);
}

// 服务实现类
public class UserService : IUserService
{
    public string GetUserName(int id)
    {
        return $"用户{id}";
    }
}

public class OrderService : IOrderService
{
    public string GetOrderInfo(int orderId)
    {
        return $"订单{orderId}";
    }
}

使用Scrutor批量注册这些服务的代码如下:

using Microsoft.Extensions.DependencyInjection;
using Scrutor;

var services = new ServiceCollection();

// 扫描当前程序集,批量注册服务
services.Scan(scan => scan
    // 从当前执行的程序集开始扫描
    .FromAssemblyOf<IUserService>()
    // 筛选要注册的类型:类是公开的、非抽象的
    .AddClasses(classes => classes.Where(type => type.Name.EndsWith("Service")))
    // 将类注册为所有它实现的接口
    .AsImplementedInterfaces()
    // 设置服务生命周期为瞬时
    .WithTransientLifetime());

var serviceProvider = services.BuildServiceProvider();
var userService = serviceProvider.GetRequiredService<IUserService>();
Console.WriteLine(userService.GetUserName(1));

常用配置规则说明

程序集选择

Scrutor支持多种程序集选择方式,常用的有:

  • FromAssemblyOf<T>():从包含类型T的程序集开始扫描
  • FromAssemblies(params Assembly[] assemblies):指定多个具体程序集扫描
  • FromAssemblyDependencies(Assembly assembly):扫描指定程序集及其依赖的所有程序集

类型筛选

通过AddClasses方法可以筛选要注册的类型,支持多种筛选条件:

// 注册所有公开的非抽象类
.AddClasses(classes => classes.Public())

// 注册指定命名空间下的类
.AddClasses(classes => classes.InNamespaces("MyApp.Services"))

// 注册带有指定特性的类
.AddClasses(classes => classes.WithAttribute<MyCustomAttribute>())

服务映射规则

注册类型后需要指定服务类型的映射规则,常用的有:

  • AsSelf():将类型注册为自身,即services.AddTransient<UserService>()
  • AsImplementedInterfaces():注册为类型实现的所有接口
  • As<TService>():注册为指定的服务类型
  • AsMatchingInterface():按照名称匹配接口,比如UserService会匹配IUserService

生命周期配置

Scrutor支持三种标准的依赖注入生命周期:

  • WithTransientLifetime():瞬时生命周期,每次获取都创建新实例
  • WithScopedLifetime():作用域生命周期,同一作用域内获取同一实例
  • WithSingletonLifetime():单例生命周期,全局唯一实例

高级用法示例

按条件设置不同生命周期

如果有部分服务需要单例,部分需要瞬时,可以通过条件判断分别配置:

services.Scan(scan => scan
    .FromAssemblyOf<IUserService>()
    .AddClasses(classes => classes.Where(type => type.Name.EndsWith("Service")))
    .AsImplementedInterfaces()
    .WithLifetime(lifetimeSelector => 
        lifetimeSelector.If(type => type.Name.EndsWith("CacheService"), 
            lifetime => lifetime.WithSingletonLifetime())
            .Else(lifetime => lifetime.WithTransientLifetime())));

排除指定类型

如果不想注册某些特定类型,可以在筛选时排除:

services.Scan(scan => scan
    .FromAssemblyOf<IUserService>()
    .AddClasses(classes => classes
        .Where(type => type.Name.EndsWith("Service"))
        // 排除测试用的服务类
        .Where(type => !type.Name.Contains("Test")))
    .AsImplementedInterfaces()
    .WithTransientLifetime());

注意事项

使用Scrutor批量注册时需要注意几个问题:首先,扫描的程序集范围不要过大,避免扫描到不需要的程序集导致注册冗余服务;其次,如果同一个服务类型有多个实现,批量注册会全部注册,获取时如果需要指定实现需要额外配置;最后,Scrutor的注册规则和手动注册不冲突,两者可以混合使用,手动注册的优先级高于批量注册的结果。

通过Scrutor的批量扫描和自动注册能力,开发者可以将原本需要数十行甚至上百行的服务注册代码简化成几行配置,大幅降低维护成本,尤其适合中大型项目的依赖注入管理。

C#Scrutor依赖注入批量注册服务扫描修改时间:2026-07-05 14:15:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。