百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

C#.NET Autofac 详解(c# autoit)

bigegpt 2025-07-27 18:52 4 浏览

简介

Autofac 是一个成熟的、功能丰富的 .NET 依赖注入(DI)容器。

相比于内置容器,它额外提供:模块化注册、装饰器(Decorator)、拦截器(Interceptor)、强o的属性/方法注入支持、基于约定的程序集扫描等特性。

核心组件

  • ContainerBuilder:用于注册服务的构建器
  • IContainer:服务容器,负责解析依赖
  • ILifetimeScope:生命周期作用域,管理对象生命周期
  • Module:模块化注册的基类

核心特性

灵活的服务注册

  • 支持按类型、实例、工厂、委托等多种方式注册;
  • 支持开放泛型(IRepository<T> → Repository<T>)、条件注册。

生命周期管理

  • 同样有 Singleton、InstancePerDependency(每次)、InstancePerLifetimeScope(等同于 Scoped)、InstancePerMatchingLifetimeScope(自定义标签作用域)等多种模式。

模块化(Module)

  • 通过继承 Module 将相关注册逻辑封装为可复用、可拆分的单元;
  • 支持自动加载整个程序集中的 Module

装饰器(Decorator)

  • 可以很方便地为某个服务添加一层或多层“外衣”,例如日志、缓存等横切逻辑。

拦截器(Interceptor)

  • 基于 Castle DynamicProxy,自动在方法调用前后执行 AOP 逻辑,如性能监控、事务管理等。

程序集扫描

  • 支持按命名空间、接口、特性等约定,将多个实现一行注册。

基本使用

引入 NuGet

Install-Package Autofac
Install-Package Autofac.Extensions.DependencyInjection   # ASP.NET Core 集成

最简示例

using Autofac;

var builder = new ContainerBuilder();

// 1. 注册具体类型(默认使用 Transient 生命周期)
builder.RegisterType<OrderService>();

// 2. 注册接口与实现
builder.RegisterType<DbOrderRepository>().As<IOrderRepository>();

// 3. 注册单例
builder.RegisterType<AppConfig>().SingleInstance();

// 4. 注册工厂方法
builder.Register(c => new HttpClient()).InstancePerLifetimeScope();

builder.Register(c => {
    var config = c.Resolve<IConfiguration>();
    return new MyService(config.GetConnectionString("Default"));
}).As<IMyService>();

// 5. 注册已存在的实例
var logger = new NLogLogger();
builder.RegisterInstance(logger).As<ILogger>();

// 6. 注册开放泛型类型
builder.RegisterGeneric(typeof(MyRepository<>)).As(typeof(IRepository<>));

// 构建容器
var container = builder.Build();

// 从容器中解析服务
using (var scope = container.BeginLifetimeScope()) {
    var service = scope.Resolve<OrderService>();
}

服务暴露 (Exposing Services)

As<T>(): 将组件暴露为特定服务类型 T (通常是接口)

builder.RegisterType<EmailSender>().As<IEmailSender>();

As<TService1, TService2>(): 将组件暴露为多个服务类型

builder.RegisterType<FileLogger>().As<ILogger, IFileLogger>();

AsImplementedInterfaces(): 将组件暴露为其实现的所有公共接口

builder.RegisterType<CustomerRepository>().AsImplementedInterfaces();
// 等同于 .As<ICustomerRepository, IRepository<Customer>, ...>()

AsSelf(): 将组件暴露为其自身类型。通常与其他.As()一起使用

builder.RegisterType<MySpecialService>().AsSelf().As<ISpecialService>();

生命周期(Scope)管理

生命周期

对应 Autofac 方法

场景

瞬时 / 每次依赖

.InstancePerDependency() (默认)

无状态、轻量对象

单例 / 容器范围

.SingleInstance()

线程安全、全局共享

每个生命周期作用域

.InstancePerLifetimeScope()

类似 ASP.NET Core 的 Scoped 模式

每个 HTTP 请求内单例

.InstancePerRequest()

仅 ASP.NET Core 集成支持

自定义标记作用域

.InstancePerMatchingLifetimeScope("tag")

某些特定操作需独立作用域

builder.RegisterType<CacheService>()
       .As<ICacheService>()
       .SingleInstance();

builder.RegisterType<DbContext>()
       .AsSelf()
       .InstancePerLifetimeScope();

var tagScope = container.BeginLifetimeScope("unitOfWork");
var ctx = tagScope.Resolve<DbContext>();  // 属于 "unitOfWork" 作用域

高级特性

属性注入

public class MyService {
    [Inject] // 注入属性
    public ILogger Logger { get; set; }  // 自动注入的属性
}

// 注册时启用属性注入
builder.RegisterType<MyService>()
       .ProjertiesAutowired();

手动解析

public class MyService
{
    private readonly IComponentContext _context;

    public MyService(IComponentContext context)
    {
        _context = context;
    }

    public void DoWork()
    {
        var userService = _context.Resolve<IUserService>();
        // 使用 userService
    }
}

命名与键控服务

// 注册多个实现,使用命名区分
builder.RegisterType<SqlDbContext>().Named<DbContext>("sql");
builder.RegisterType<MongoDbContext>().Named<DbContext>("mongo");

// 解析时指定名称
var sqlContext = scope.ResolveNamed<DbContext>("sql");

集合解析

自动解析所有实现某一接口的服务

container.RegisterType<UserService1>().As<IUserService>();
container.RegisterType<UserService2>().As<IUserService>();

// 解析所有实现
public class MultiService
{
    private readonly IEnumerable<IUserService> _services;

    public MultiService(IEnumerable<IUserService> services)
    {
        _services = services;
    } 
}

作用域管理

using (var scope = container.BeginLifetimeScope())
{
    var service = scope.Resolve<IUserService>();
    // 使用 service
}

高级作用域控制

  • 嵌套作用域
  using (var parentScope = container.BeginLifetimeScope())
  {
      var serviceA = parentScope.Resolve<ServiceA>();
      using (var childScope = parentScope.BeginLifetimeScope())
      {
          var serviceB = childScope.Resolve<ServiceB>(); // 可访问父作用域实例
      }
  }
  • 带标签作用域 (Tagged Scopes)
  // 注册时标记作用域
  builder.RegisterType<EmailSender>()
         .As<IEmailSender>()
         .InstancePerMatchingLifetimeScope("transaction");

  // 使用标签创建作用域
  using (var transactionScope = container.BeginLifetimeScope("transaction"))
  {
      var emailSender = transactionScope.Resolve<IEmailSender>(); // 事务内共享实例
  }

模块化注册

当项目庞大或有多个子系统时,将注册逻辑封装在 Module 中,便于维护与复用。

// 定义模块
public class DataModule : Module {
    protected override void Load(ContainerBuilder builder) {
        builder.RegisterType<DbConnection>().As<IDbConnection>();
        builder.RegisterType<OrderRepository>().As<IOrderRepository>();
    }
}

// 注册模块
builder.RegisterModule<DataModule>();

public class RepositoryModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        // 自动扫描程序集内的 IRepository<> 实现
        builder.RegisterAssemblyTypes(typeof(RepositoryModule).Assembly)
               .AsClosedTypesOf(typeof(IRepository<>))
               .InstancePerLifetimeScope();
    }
}

// 在主程序里加载
var builder = new ContainerBuilder();
builder.RegisterModule<RepositoryModule>();
builder.RegisterModule(new SettingsModule(settings));

装饰器(Decorator)

给已有服务动态“套”上日志、缓存等功能,不需改动原实现。

// 原始服务
builder.RegisterType<OrderService>()
       .As<IOrderService>();

// 装饰器:构造参数 inner 实例即被装饰的服务
builder.RegisterDecorator<LoggingOrderService, IOrderService>();
  • 等同于:当解析 IOrderService 时,先创建 OrderService,再将其传给 LoggingOrderService 构造器。

AOP 拦截与动态代理

基于 Castle DynamicProxy,为接口或虚方法生成代理,在调用前后执行拦截逻辑。

引入包

Install-Package Autofac.Extras.DynamicProxy
Install-Package Castle.Core
// 定义拦截器
public class LoggingInterceptor : IInterceptor {
    public void Intercept(IInvocation invocation) {
        Console.WriteLine(#34;调用方法: {invocation.Method.Name}");
        invocation.Proceed();  // 执行原始方法
        Console.WriteLine(#34;方法返回: {invocation.ReturnValue}");
    }
}

// 注册带拦截器的服务
builder.RegisterType<OrderService>()
       .As<IOrderService>()
       .EnableInterfaceInterceptors()
       .InterceptedBy(typeof(LoggingInterceptor));

builder.RegisterType<LoggingInterceptor>();

程序集扫描与约定注册

根据命名、接口或特性,批量注册类型:

// 按接口后缀约定:所有以 "Service" 结尾的类,注册为它们所实现的接口
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
       .Where(t => t.Name.EndsWith("Service"))
       .AsImplementedInterfaces()
       .InstancePerLifetimeScope();

条件注册

builder.RegisterType<SqlRepository>()
       .As<IRepository>()
       .When(c => c.Parameters.Any(p => p.Name == "useSql" && (bool)p.Value));

装配时验证

// 验证所有注册的服务可被解析
container.AssertConfigurationIsValid();

循环依赖解决

延迟注入

  builder.Register(c => new ServiceA(c.Resolve<Lazy<IServiceB>>()));
builder.Register(c => new ServiceA(c.Resolve<Func<IServiceB>>()))
       .As<IServiceA>();
builder.Register(c => new ServiceB(c.Resolve<IServiceA>()))
       .As<IServiceB>();
builder.RegisterType<ServiceA>().As<IService>()
       .OnlyIf(reg => Environment.IsDevelopment);

混合使用内置 DI 和 Autofac

builder.Services.AddScoped<IOtherService, OtherService>(); // 内置 DI
builder.Host.ConfigureContainer<ContainerBuilder>(container =>
{
    container.RegisterType<UserService>().As<IUserService>();
});

与 ASP.NET Core 集成

Program.cs 中替换容器

// Program.cs
using Autofac.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// 使用 Autofac 替换默认 DI 容器
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

// 配置 Autofac 服务
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => {
    containerBuilder.RegisterType<CustomService>().As<IService>();
    containerBuilder.RegisterModule<MyModule>();
});

var app = builder.Build();
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureContainer<ContainerBuilder>(builder =>
        {
            builder.RegisterModule<RepositoryModule>();
            //… 其他注册
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

在控制台应用中使用

var builder = new ContainerBuilder();
builder.RegisterModule<ApplicationModule>();
var container = builder.Build();

using (var scope = container.BeginLifetimeScope()) {
    var service = scope.Resolve<IMyService>();
    service.Run();
}

最佳实践与常见问题

避免服务定位器反模式

// 反模式:直接从容器解析服务
var service = container.Resolve<IMyService>();

// 正确做法:通过构造函数注入
public class MyConsumer {
    private readonly IMyService _service;
    public MyConsumer(IMyService service) { _service = service; }
}

相关推荐

C#.NET Autofac 详解(c# autoit)

简介Autofac是一个成熟的、功能丰富的.NET依赖注入(DI)容器。相比于内置容器,它额外提供:模块化注册、装饰器(Decorator)、拦截器(Interceptor)、强o的属性/方法注...

webapi 全流程(webapi怎么部署)

C#中的WebAPIMinimalApi没有控制器,普通api有控制器,MinimalApi是直达型,精简了很多中间代码,广泛适用于微服务架构MinimalApi一切都在组控制台应用程序类【Progr...

.NET外挂系列:3. 了解 harmony 中灵活的纯手工注入方式

一:背景1.讲故事上一篇我们讲到了注解特性,harmony在内部提供了20个HarmonyPatch重载方法尽可能的让大家满足业务开发,那时候我也说了,特性虽然简单粗暴,但只能解决95%...

C# 使用SemanticKernel调用本地大模型deepseek

一、先使用ollama部署好deepseek大模型。具体部署请看前面的头条使用ollama进行本地化部署deepseek大模型二、创建一个空的控制台dotnetnewconsole//添加依赖...

C#.NET 中间件详解(.net core中间件use和run)

简介中间件(Middleware)是ASP.NETCore的核心组件,用于处理HTTP请求和响应的管道机制。它是基于管道模型的轻量级、模块化设计,允许开发者在请求处理过程中插入自定义逻辑。...

IoC 自动注入:让依赖注册不再重复劳动

在ASP.NETCore中,IoC(控制反转)功能通过依赖注入(DI)实现。ASP.NETCore有一个内置的依赖注入容器,可以自动完成依赖注入。我们可以结合反射、特性或程序集扫描来实现自动...

C#.NET 依赖注入详解(c#依赖注入的三种方式)

简介在C#.NET中,依赖注入(DependencyInjection,简称DI)是一种设计模式,用于实现控制反转(InversionofControl,IoC),以降低代码耦合、提高可...

C#从零开始实现一个特性的自动注入功能

在现代软件开发中,依赖注入(DependencyInjection,DI)是实现松耦合、模块化和可测试代码的一个重要实践。C#提供了优秀的DI容器,如ASP.NETCore中自带的Micr...

C#.NET 仓储模式详解(c#仓库货物管理系统)

简介仓储模式(RepositoryPattern)是一种数据访问抽象模式,它在领域模型和数据访问层之间创建了一个隔离层,使得领域模型无需直接与数据访问逻辑交互。仓储模式的核心思想是将数据访问逻辑封装...

C#.NET 泛型详解(c# 泛型 滥用)

简介泛型(Generics)是指在类型或方法定义时使用类型参数,以实现类型安全、可重用和高性能的数据结构与算法为什么需要泛型类型安全防止“装箱/拆箱”带来的性能损耗,并在编译时检测类型错误。可重用同一...

数据分析-相关性分析(相关性 分析)

相关性分析是一种统计方法,用于衡量两个或多个变量之间的关系强度和方向。它通过计算相关系数来量化变量间的线性关系,从而帮助理解变量之间的相互影响。相关性分析常用于数据探索和假设检验,是数据分析和统计建模...

geom_smooth()函数-R语言ggplot2快速入门18

在每节,先运行以下这几行程序。library(ggplot2)library(ggpubr)library(ggtext)#用于个性化图表library(dplyr)#用于数据处理p...

规范申报易错要素解析(规范申报易错要素解析)

为什么要规范申报?规范申报是以满足海关监管、征税、统计等工作为目的,纳税义务人及其代理人依法向海关如实申报的行为,也是海关审接单环节依法监管的重要工作。企业申报的内容须符合《中华人民共和国海关进出口货...

「Eurora」海关编码归类 全球海关编码查询 关务服务

  海关编码是什么?  海关编码即HS编码,为编码协调制度的简称。  其全称为《商品名称及编码协调制度的国际公约》(InternationalConventionforHarmonizedCo...

9月1日起,河南省税务部门对豆制品加工业试行新政7类豆制品均适用投入产出法

全媒体记者杨晓川报道9月2日,记者从税务部门获悉,为减轻纳税人税收负担,完善农产品增值税进项税额抵扣机制,根据相关规定,结合我省实际情况,经广泛调查研究和征求意见,从9月1日起,我省税务部门对豆制品...