引言
在 .NET 依赖注入(DI)生态中,Autofac 凭借其强大的功能扩展性和灵活的配置方式,成为企业级应用的首选容器。它不仅覆盖了基础的依赖注入需求,更通过丰富的核心属性和特性,解决了复杂场景下的依赖管理问题。本文将详细介绍 Autofac 的核心属性、使用方法及实战场景,帮助开发者快速上手并灵活运用。
一、核心组件与基础属性
Autofac 的核心能力围绕四大组件展开,各组件的关键属性直接决定了依赖注入的实现方式:
1. ContainerBuilder(服务构建器)
作为服务注册的核心入口,ContainerBuilder 提供了多种注册相关的属性与方法,支撑不同场景的服务注册:
- RegisterType() :按类型注册服务,默认生命周期为瞬时(InstancePerDependency),适用于无状态轻量对象。示例:
builder.RegisterType<OrderService>(); - RegisterInstance(instance) :注册已实例化的对象,适用于第三方组件实例(如日志组件),需注意实例的生命周期管理。示例:
var logger = new NLogLogger(); builder.RegisterInstance(logger).As<ILogger>(); - RegisterGeneric(typeof(T<>)) :支持开放泛型注册,自动匹配泛型参数,大幅简化仓储模式等通用组件的注册。示例:
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); - Register(c => ...) :通过工厂方法注册,支持复杂依赖逻辑(如读取配置、动态创建对象)。示例:
builder.Register(c => new MyService(c.Resolve<IConfiguration>().GetConnectionString("Default"))).As<IMyService>();
2. IContainer(服务容器)
由 ContainerBuilder.Build() 生成,是服务解析的核心容器,关键属性与方法包括:
- BeginLifetimeScope() :创建生命周期作用域,用于管理对象的创建与释放,支持嵌套作用域和标签作用域。
- Resolve() :从容器中解析指定类型的服务,自动处理依赖链注入。
- AssertConfigurationIsValid() :验证所有注册服务是否可正常解析,提前排查依赖缺失问题。
3. ILifetimeScope(生命周期作用域)
负责管理对象的生命周期,核心属性即生命周期配置方法,决定了对象的创建频率与存活范围:
- InstancePerDependency() :默认生命周期,每次解析都创建新实例,适用于无状态组件。
- SingleInstance() :单例模式,容器范围内仅创建一个实例,适用于全局配置、线程安全组件。
- InstancePerLifetimeScope() :作用域内单例,同一作用域下多次解析返回同一实例,类似 ASP.NET Core 的 Scoped 模式,适用于数据库上下文等。
- InstancePerMatchingLifetimeScope("tag") :自定义标签作用域,仅在标记相同的作用域内共享实例,适用于事务、单元操作等场景。
- InstancePerRequest() :仅支持 ASP.NET Core 集成,HTTP 请求内单例,适用于请求级别的资源共享。
4. Module(模块化注册基类)
用于封装注册逻辑,核心属性为 Load(ContainerBuilder builder) 方法,通过继承 Module 可实现注册逻辑的拆分与复用:
- 示例:
csharp
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(AutofacModule).Assembly).AsClosedTypesOf(typeof(IRepository<>));
}
}
二、服务暴露与高级属性配置
1. 服务暴露属性(As 系列方法)
用于指定服务的暴露类型,决定了服务可通过哪些接口或类型被解析:
- As() :将服务暴露为指定接口类型,是最常用的配置。示例:
builder.RegisterType<EmailSender>().As<IEmailSender>(); - As<T1, T2>() :暴露为多个服务类型,支持同一实现类适配多个接口。示例:
builder.RegisterType<FileLogger>().As<ILogger, IFileLogger>(); - AsImplementedInterfaces() :自动暴露实现的所有公共接口,避免多接口注册的繁琐。示例:
builder.RegisterType<CustomerRepository>().AsImplementedInterfaces(); - AsSelf() :暴露为服务自身类型,可与其他
As方法组合使用。示例:builder.RegisterType<MyService>().AsSelf().As<IMyService>();
2. 高级特性属性
(1)属性注入相关
- PropertiesAutowired() :启用属性注入,配合
[Inject]特性可实现属性级别的依赖注入(推荐优先使用构造函数注入)。示例:builder.RegisterType<MyService>().PropertiesAutowired();类定义:public class MyService { [Inject] public ILogger Logger { get; set; } }
(2)命名与键控服务
- Named("name") :为服务注册指定名称,解决同一接口多个实现的区分问题。示例:
builder.RegisterType<SqlDbContext>().Named<DbContext>("sql"); - ResolveNamed("name") :按名称解析服务。示例:
var sqlContext = scope.ResolveNamed<DbContext>("sql");
(3)装饰器与拦截器
- RegisterDecorator<DecoratorT, ServiceT>() :为服务添加装饰器,封装横切逻辑(日志、缓存等)。示例:
builder.RegisterDecorator<LoggingOrderService, IOrderService>(); - EnableInterfaceInterceptors() + InterceptedBy(typeof(Interceptor)) :启用接口拦截器,基于 Castle DynamicProxy 实现 AOP 逻辑。示例:
builder.RegisterType<OrderService>().As<IOrderService>().EnableInterfaceInterceptors().InterceptedBy(typeof(LoggingInterceptor));
(4)程序集扫描与条件注册
- RegisterAssemblyTypes(assemblies) :扫描指定程序集,批量注册符合条件的类型。示例:
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces(); - When(c => condition) :条件注册,满足指定条件时才注册服务。示例:
builder.RegisterType<SqlRepository>().As<IRepository>().When(c => c.Parameters.Any(p => p.Name == "useSql" && (bool)p.Value));
三、实战场景:核心属性的综合运用
1. ASP.NET Core 集成
添加引用
C#
Install-Package Autofac
Install-Package Autofac.Extensions.DependencyInjection
在 Program.cs 中替换默认容器,配置核心属性:
C#
var builder = WebApplication.CreateBuilder(args);
// 启用 Autofac 容器
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// 配置 Autofac 属性
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => {
// 注册模块
containerBuilder.RegisterModule(new AutofacModule());
// 注册服务并指定生命周期
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
// 工厂方法注册
containerBuilder.Register(c => new HttpClient()).SingleInstance();
});
2. 循环依赖解决
通过 Lazy<T> 延迟注入属性解决循环依赖:
ini
builder.Register(c => new ServiceA(c.Resolve<Lazy<IServiceB>>())).As<IServiceA>();
builder.Register(c => new ServiceB(c.Resolve<IServiceA>())).As<IServiceB>();
3. 自定义标签作用域
为事务操作创建独立作用域:
swift
// 注册时指定标签作用域
builder.RegisterType<TransactionService>().As<ITransactionService>().InstancePerMatchingLifetimeScope("transaction");
// 使用标签创建作用域
using (var transactionScope = container.BeginLifetimeScope("transaction")) {
var service = transactionScope.Resolve<ITransactionService>();
}
四、使用注意事项
- 优先使用构造函数注入,属性注入仅用于特殊场景,避免依赖关系不透明。
- 合理配置生命周期,避免单例服务依赖瞬时服务,或作用域服务跨作用域使用导致的内存泄漏。
- 大型项目推荐使用模块化注册,拆分不同模块的注册逻辑,提升可维护性。
- 避免直接从容器解析服务(服务定位器反模式),坚持依赖注入的设计思想。
Autofac 的核心属性与特性覆盖了从简单到复杂的各类依赖管理场景,通过灵活运用这些属性,能够有效降低代码耦合、提升开发效率与可维护性。无论是小型工具类项目还是大型企业级应用,Autofac 都能提供稳定、高效的依赖注入支持,成为 .NET 开发者的得力工具。