# Autofac 完整详解 + 全部注册方式实战案例
Autofac 完整详解 + 全部注册方式实战案例
一、Autofac 核心概述
1. 什么是 Autofac
Autofac 是 .NET 生态最灵活、功能最全的依赖注入DI容器,支持 .NET Framework / .NET Core / .NET 5~8,完美适配控制台、WPF、ASP.NET Core、WinForms。
核心优势:
- 灵活的生命周期管理(瞬时、单例、作用域、线程作用域等)
- 批量注册、程序集扫描、泛型自动注入
- 属性注入、构造注入、方法注入多模式
- 模块拆分注册、条件注册、命名/键服务、延迟加载 Lazy
- 与 ASP.NET Core、WPF MVVM、SqlSugar、NLog 无缝集成
2. 基础术语
- 接口(Service):对外暴露抽象
IUserService - 实现(Implementation):具体类
UserService - 容器容器(ContainerBuilder):注册所有类型的构建器
- IContainer:构建完成的根容器,全局唯一
- ILifetimeScope:作用域容器,子容器,释放时自动销毁实例
- 生命周期:控制对象创建与销毁时机
3. NuGet 安装
<!-- 核心包 --> Install-Package Autofac <!-- ASP.NET Core 适配(web项目专用) --> Install-Package Autofac.Extensions.DependencyInjection二、完整项目基础示例(统一测试实体)
先定义统一测试接口与实现,所有注册案例复用:
// 业务接口 public interface IUserService { void Show(); } // 普通实现类 public class UserService : IUserService { public void Show() { Console.WriteLine("UserService 执行"); } } // 带构造参数依赖 public interface IOrderRepo { } public class OrderRepo : IOrderRepo { } public class OrderService { private readonly IOrderRepo _repo; public string Name { get; set; } // 用于属性注入测试 // 构造依赖 public OrderService(IOrderRepo repo) { _repo = repo; } public void Print() { Console.WriteLine($"OrderService, 属性值:{Name}"); } } // 泛型测试 public interface IRepository<T> { } public class Repository<T> : IRepository<T> { } // 模块拆分专用模块类 public class BusinessModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<UserService>().As<IUserService>(); } }三、Autofac 全部注册方式 + 可运行案例
前置统一初始化代码(所有案例共用)
// 1. 创建构建器 var builder = new ContainerBuilder(); // ===== 此处填写下面任意注册代码 ===== // 2. 构建根容器 IContainer container = builder.Build(); // 3. 创建作用域(推荐,避免直接用根容器Resolve) using var scope = container.BeginLifetimeScope(); // 4. 解析服务使用 var user = scope.Resolve<IUserService>(); user.Show();分类1:基础单类型注册(最常用)
1.1 仅注册自身(不绑定接口)
// 只能 Resolve<UserService>(),不能用 IUserService builder.RegisterType<UserService>(); // 解析 var svc = scope.Resolve<UserService>();1.2 注册实现并暴露接口(标准写法)
builder.RegisterType<UserService>().As<IUserService>(); // 解析:scope.Resolve<IUserService>()1.3 一个实现绑定多个接口
public interface IBase { } public class UserService : IUserService, IBase { } builder.RegisterType<UserService>() .As<IUserService>() .As<IBase>();1.4 AsSelf() 同时暴露自身+接口
builder.RegisterType<UserService>() .As<IUserService>() .AsSelf(); // 两种方式都能解析 scope.Resolve<IUserService>(); scope.Resolve<UserService>();分类2:实例注册(手动new对象,容器不负责创建)
2.1 RegisterInstance 注册现成对象
适合静态配置、第三方SDK实例、单例固定对象
var userSvc = new UserService(); builder.RegisterInstance(userSvc).As<IUserService>(); // 生命周期强制为单例,容器不会新建2.2 RegisterInstance + 外部传入配置
var config = new AppConfig { ConnectionString = "test" }; builder.RegisterInstance(config).SingleInstance();分类3:Lambda工厂注册 Register.Register
3.1 简单Lambda创建实例
手动控制构造逻辑,灵活传参
builder.Register(ctx => { // ctx 是当前作用域,可以解析依赖 var repo = ctx.Resolve<IOrderRepo>(); return new OrderService(repo); }).AsSelf();3.2 带参数构造、动态赋值
builder.Register(ctx => { var repo = ctx.Resolve<IOrderRepo>(); var orderSvc = new OrderService(repo); orderSvc.Name = "工厂赋值"; return orderSvc; }).AsSelf();3.3 无依赖简单工厂
builder.Register(_ => new UserService()).As<IUserService>();分类4:泛型批量注册(仓储层必备)
4.1 开放泛型注册 RegisterGeneric
// 自动适配 IRepository<User> IRepository<Order> builder.RegisterGeneric(typeof(Repository<>)) .As(typeof(IRepository<>)); // 使用 var userRepo = scope.Resolve<IRepository<User>>(); var orderRepo = scope.Resolve<IRepository<Order>>();分类5:程序集批量扫描注册(大型项目核心)
5.1 扫描当前程序集,接口以I开头、实现同命名
var assembly = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyTypes(assembly) // 筛选:只导出 public 类 .PublicOnly() // 匹配规则:实现 IXXX 的 XXX 类 .Where(t => t.Name.StartsWith("User") || t.Name.EndsWith("Service")) // 自动绑定对应接口 .AsImplementedInterfaces() // 默认瞬时生命周期 .InstancePerDependency();5.2 多程序集扫描(分层架构:Service、Repository)
var asm1 = Assembly.Load("Project.Service"); var asm2 = Assembly.Load("Project.Repository"); builder.RegisterAssemblyTypes(asm1, asm2) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces();5.3 排除特定类型、只注册自身
builder.RegisterAssemblyTypes(assembly) .Except<UserService>() // 排除UserService .AsSelf();分类6:模块拆分注册 Module(大型项目解耦)
6.1 定义Module(前文 BusinessModule)
public class BusinessModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<UserService>().As<IUserService>(); builder.RegisterType<OrderRepo>().As<IOrderRepo>(); } }6.2 加载模块
// 方式1:直接new模块 builder.RegisterModule(new BusinessModule()); // 方式2:按程序集扫描所有Module自动加载 builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());分类7:属性注入、方法注入、构造参数覆盖
7.1 属性注入 PropertiesAutowired()
自动给类中公共属性注入依赖
builder.RegisterType<OrderService>() .AsSelf() .PropertiesAutowired(); // 自动填充所有可解析属性 // 如果只想注入指定属性 builder.RegisterType<OrderService>() .AsSelf() .WithProperty("Name", "手动赋值");7.2 构造参数显式赋值 WithParameter
覆盖构造函数参数,固定值/从容器解析
// 固定值参数 builder.RegisterType<OrderService>() .WithParameter("repo", new OrderRepo()) .AsSelf(); // 从容器解析参数 builder.RegisterType<OrderService>() .WithParameter( (pi, ctx) => pi.Name == "repo", (pi, ctx) => ctx.Resolve<IOrderRepo>() );7.3 方法注入 OnActivated / OnActivating
实例创建前后回调,做初始化
builder.RegisterType<OrderService>() .AsSelf() .OnActivating(ctx => { // 创建前执行 var svc = ctx.Instance as OrderService; svc.Name = "激活前赋值"; }) .OnActivated(ctx => { // 创建完成后执行初始化方法 var svc = ctx.Instance as OrderService; svc.Print(); });分类8:命名服务、键服务(同一接口多实现)
8.1 命名服务 Named
// 两个实现 builder.RegisterType<UserService>().Named<IUserService>("admin"); builder.RegisterType<CustomerUserService>().Named<IUserService>("customer"); // 解析指定名称 var adminSvc = scope.ResolveNamed<IUserService>("admin");8.2 键服务 Keyed(用枚举/常量做Key)
public enum UserType { Admin, Customer } builder.RegisterType<UserService>().Keyed<IUserService>(UserType.Admin); builder.RegisterType<CustomerUserService>().Keyed<IUserService>(UserType.Customer); var cusSvc = scope.ResolveKeyed<IUserService>(UserType.Customer);8.3 全部解析 ResolveAll
同一接口多个实现全部取出
var allServices = scope.Resolve<IEnumerable<IUserService>>(); foreach (var s in allServices) s.Show();分类9:延迟加载 Lazy、Func 工厂注入
9.1 Lazy 延迟实例化(使用时才创建)
无需额外注册,直接构造注入Lazy<IUserService>
public class TestApp { private readonly Lazy<IUserService> _lazyUser; public TestApp(Lazy<IUserService> lazyUser) { _lazyUser = lazyUser; } public void Run() { // 第一次访问Value才创建对象 _lazyUser.Value.Show(); } } builder.RegisterType<TestApp>();9.2 Func 动态多次创建实例
public class TestApp { private readonly Func<IUserService> _userFactory; public TestApp(Func<IUserService> userFactory) { _userFactory = userFactory; } public void MultiCreate() { var u1 = _userFactory(); var u2 = _userFactory(); } }四、五大生命周期详解(所有生命周期注册写法)
生命周期控制实例复用规则,开发最容易踩坑
| 生命周期 | 说明 | 适用场景 |
|---|---|---|
| InstancePerDependency(默认瞬时) | 每次Resolve新建 | 无状态服务、轻量工具 |
| SingleInstance(全局单例) | 整个容器唯一 | 配置、日志、连接池 |
| InstancePerLifetimeScope(作用域单例) | 每个子Scope一个实例 | 数据库上下文、请求级服务 |
| InstancePerMatchingLifetimeScope | 指定Tag作用域单例 | WPF多窗口、多租户 |
| InstancePerRequest | ASP.NET Core请求单例 | Web项目专用 |
4.1 瞬时(默认,可省略)
builder.RegisterType<UserService>() .As<IUserService>() .InstancePerDependency();4.2 全局单例 SingleInstance
builder.RegisterType<UserService>() .As<IUserService>() .SingleInstance();4.3 作用域单例 InstancePerLifetimeScope
builder.RegisterType<OrderRepo>() .As<IOrderRepo>() .InstancePerLifetimeScope();4.4 标记作用域单例(多窗口WPF常用)
// 注册带Tag匹配 builder.RegisterType<UserService>() .As<IUserService>() .InstancePerMatchingLifetimeScope("MainWindow"); // 创建带Tag的作用域 using var windowScope = container.BeginLifetimeScope("MainWindow");4.5 ASP.NET Core 请求级单例
builder.RegisterType<DbContext>() .InstancePerRequest();五、容器解析 Resolve 全部用法
using var scope = container.BeginLifetimeScope(); // 1. 基础解析 var user = scope.Resolve<IUserService>(); // 2. 安全解析(不存在不抛异常,返回null) if (scope.TryResolve<IUserService>(out var safeUser)) { safeUser.Show(); } // 3. 命名/键解析 var admin = scope.ResolveNamed<IUserService>("admin"); var cus = scope.ResolveKeyed<IUserService>(UserType.Customer); // 4. 批量解析全部实现 var list = scope.Resolve<IEnumerable<IUserService>>(); // 5. 带参数解析(构造动态传参) var order = scope.Resolve<OrderService>(new NamedParameter("repo", new OrderRepo()));六、ASP.NET Core 集成 Autofac 完整案例
Program.cs
var builder = WebApplication.CreateBuilder(args); // 替换默认DI为Autofac builder.Host.ConfigureContainer<ContainerBuilder>(autofacBuilder => { // 1. 批量扫描Service层 var asm = Assembly.Load("Project.Service"); autofacBuilder.RegisterAssemblyTypes(asm) .AsImplementedInterfaces() .InstancePerLifetimeScope(); // 2. 加载模块 autofacBuilder.RegisterModule(new BusinessModule()); }); var app = builder.Build();七、WPF 集成 Autofac 通用模板
var containerBuilder = new ContainerBuilder(); // 注册ViewModel、Service containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => t.Name.EndsWith("ViewModel")) .AsSelf() .InstancePerLifetimeScope(); IContainer container = containerBuilder.Build(); // 全局作用域 App.Container = container; // 打开窗口时创建子Scope using var scope = container.BeginLifetimeScope(); var mainVm = scope.Resolve<MainViewModel>(); var window = new MainWindow { DataContext = mainVm }; window.Show();常见踩坑总结
- 不要直接使用根容器
container.Resolve(),必须BeginLifetimeScope释放资源 - 单例不能依赖作用域实例,会造成生命周期泄漏
- 批量扫描时注意过滤抽象类、接口本身
- 属性注入不会覆盖构造函数赋值,构造优先
- InstancePerRequest 仅Web项目生效,控制台/WPF无效
- 注册顺序不影响解析,Autofac自动匹配依赖