当前位置:首页 > 技术 > 正文内容

Autofac在.NET Core中的依赖注入与AOP实践

访客 技术 2026年7月3日 1

1. 环境配置与NuGet包安装

首先需要引入以下NuGet包:

<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="7.1.0" />
<PackageReference Include="Castle.Core" Version="5.1.1" />

2. 替换默认DI容器

在Program.cs中配置Autofac作为服务容器,注意必须调用AddControllersAsServices()

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => 
    containerBuilder.RegisterModule(new AutofacModuleRegister()));

builder.Services.AddControllers().AddControllersAsServices();

3. 模块化注册配置

创建自定义Module类,批量注册Controller并支持属性注入:

public class AutofacModuleRegister : Autofac.Module
{
    protected override void Load(ContainerBuilder containerBuilder)
    {
        // 批量注册Controller并启用属性注入
        var controllerTypes = typeof(Program).Assembly
            .GetExportedTypes()
            .Where(type => typeof(ControllerBase).IsAssignableFrom(type))
            .ToArray();
        containerBuilder.RegisterTypes(controllerTypes).PropertiesAutowired();
        
        // 注册WineFactory供工厂模式使用
        containerBuilder.RegisterType<WineFactory>();
    }
}

4. 示例业务接口与实现

/// <summary>
/// 酒饮接口
/// </summary>
public interface IWine
{
    string Drink();
}

/// <summary>
/// 五粮液实现
/// </summary>
public class WuLiangYe : IWine
{
    public string Drink() => "当前饮用:五粮液";
}

/// <summary>
/// 茅台实现
/// </summary>
public class MaoTai : IWine
{
    public string Drink() => "当前饮用:茅台";
}

5. 依赖注入的三种方式

5.1 接口类型注入

// 注册
containerBuilder.RegisterType<WuLiangYe>().As<IWine>().InstancePerLifetimeScope();

// 使用(支持多态)
public IWine Wine { get; set; }  // 在Controller中通过属性注入

5.2 命名注入

// 注册
containerBuilder.RegisterType<WuLiangYe>().Named<IWine>(nameof(WuLiangYe)).InstancePerLifetimeScope();
containerBuilder.RegisterType<MaoTai>().Named<IWine>(nameof(MaoTai)).InstancePerLifetimeScope();

// 通过IComponentContext解析
public IWine ResolveWine(IComponentContext context, string wineName)
{
    return context.ResolveNamed<IWine>(wineName);
}

5.3 键值注入

// 注册
containerBuilder.RegisterType<WuLiangYe>().Keyed<IWine>(nameof(WuLiangYe)).InstancePerLifetimeScope();
containerBuilder.RegisterType<MaoTai>().Keyed<IWine>(nameof(MaoTai)).InstancePerLifetimeScope();

// 解析
public IWine ResolveWine(IComponentContext context, string wineName)
{
    return context.ResolveKeyed<IWine>(wineName);
}

6. 工厂模式实现

利用枚举和自定义特性实现动态解析:

6.1 枚举与特性定义

public enum WineType
{
    [WineAlias("WuLiangYe")]
    WuLiangYe = 0,
    
    [WineAlias("MaoTai")]
    MaoTai = 1
}

[AttributeUsage(AttributeTargets.Field)]
public class WineAliasAttribute : Attribute
{
    public string Alias { get; }
    public WineAliasAttribute(string alias) => Alias = alias;
}

public static class WineTypeExtensions
{
    public static string GetAlias(this WineType type)
    {
        var field = type.GetType().GetField(type.ToString());
        return field?.GetCustomAttribute<WineAliasAttribute>()?.Alias ?? "";
    }
}

6.2 工厂类实现

public class WineFactory
{
    private readonly IComponentContext _context;
    
    public WineFactory(IComponentContext context)
    {
        _context = context;
    }
    
    public IWine CreateWine(WineType wineType)
    {
        var alias = wineType.GetAlias();
        return wineType switch
        {
            WineType.WuLiangYe => _context.ResolveKeyed<IWine>(alias),
            WineType.MaoTai => _context.ResolveKeyed<IWine>(alias),
            _ => _context.ResolveNamed<IWine>(nameof(MaoTai))
        };
    }
}

7. 自动化批量注册

通过反射自动注册所有实现了IWine接口的类型:

public class AutofacModuleRegister : Autofac.Module
{
    protected override void Load(ContainerBuilder containerBuilder)
    {
        // Controller批量注册
        var controllerTypes = typeof(Program).Assembly
            .GetExportedTypes()
            .Where(type => typeof(ControllerBase).IsAssignableFrom(type))
            .ToArray();
        containerBuilder.RegisterTypes(controllerTypes).PropertiesAutowired();
        
        // 自动扫描并注册所有IWine实现
        var wineTypes = Assembly.GetEntryAssembly()!
            .ExportedTypes
            .Where(type => typeof(IWine).IsAssignableFrom(type) && !type.IsInterface)
            .ToArray();
            
        foreach (var type in wineTypes)
        {
            containerBuilder.RegisterType(type)
                .Keyed<IWine>(type.Name)
                .InstancePerLifetimeScope();
        }
        
        containerBuilder.RegisterType<WineFactory>();
    }
}

完成以上配置后,即可在Controller中通过属性注入或构造函数注入使用Autofac的依赖注入功能。推荐使用工厂模式处理需要动态解析多个实现类的场景,通过命名或键值注入可以灵活地根据运行时条件选择合适的实现。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。