使用 Autofac 实现依赖注入

前言:接上一篇文章,有了微软官方的依赖注入组件Microsoft.Extensions.DependencyInjection, 那么今天介绍一个新的开源的依赖注入组件Autofac

一、二者的差异Autofac和微软官方的依赖注入组件(Microsoft.Extensions.DependencyInjection,简称MSDI)在功能、灵活性和适用场景上存在显著差异。以下是两者的核心区别分析:

1. 功能扩展性

Autofac
①高级特性支持:提供属性注入([Inject])、方法注入基于元数据的注册(如Keyed/Named服务)、动态代理(AOP)等特性。

②模块化设计:通过Module类实现代码分组和配置复用,适合大型项目。

③生命周期管理:支持InstancePerDependency(瞬态)、SingleInstance(单例)、InstancePerLifetimeScope(作用域),并允许自定义生命周期。

④集成能力:可与第三方库(如ASP.NET Core、WPF、Unity等)深度集成,甚至替换MSDI为底层容器。

MSDI

①基础功能为主:仅支持构造函数注入和简单的生命周期(Transient、Scoped、Singleton)。
②轻量级设计:作为.NET Core内置组件,注重开箱即用,适合小型项目或快速原型开发。
与ASP.NET Core深度集成:作为框架默认容器,与中间件、配置系统无缝协作。

使用 Autofac 实现依赖注入

一、 基本依赖注入

首先,我们来看一个简单的依赖注入示例。假设我们有一个 IProductService 接口和一个 ProductService 类,以及一个 IProductRepository 接口和一个 ProductRepository 类。

定义类

public interface IProductService
{
    void SaveProduct();
}

public interface IProductRepository
{
    void GetProduct();
}

类实现

public class ProductService : IProductService
{
    public IProductRepository productRepository { get; set; }

    public void SaveProduct()
    {
        productRepository?.GetProduct();
        Console.WriteLine("保存ProductService商品成功");
    }
}

public class ProductRepository : IProductRepository
{
    public void GetProduct()
    {
        Console.WriteLine("获取商品成功");
    }
}

使用 Autofac 进行属性注入

在 Autofac 中,我们可以使用 PropertiesAutowired() 方法来实现属性注入。

using Autofac;
using System.Reflection;

public class Program
{
    public static void Main(string[] args)
    {
        // 1、创建ContainerBuilder
        ContainerBuilder containerBuilder = new ContainerBuilder();

        // 1.1、注册具体类型和接口
        containerBuilder.RegisterType<ProductService>().As<IProductService>().PropertiesAutowired(); // 属性依赖注入
        containerBuilder.RegisterType<ProductRepository>().As<IProductRepository>(); // 注入具体类型接口

        // 2、构造容器
        var container = containerBuilder.Build();

        // 3、取对象
        using (var scope = container.BeginLifetimeScope()) // 设定范围
        {
            IProductService productService = scope.Resolve<IProductService>();
            productService.SaveProduct();
        }
    }
}

在这个示例中,ProductServiceproductRepository 属性会被自动注入 ProductRepository 的实例。

二、 批量注入

在实际项目中,手动注册每个类型可能会比较繁琐。我们可以使用 Autofac 的批量注入功能来简化这个过程。

接口定义

public interface IProductService
{
    void SaveProduct();
}

public interface IOrderService
{
    void GetOrders();
}

public interface IProductRepository
{
    void GetProduct();
}

public interface IOrderRepository
{
    void GetOrders();
}

类实现

public class ProductService : IProductService
{
    public IProductRepository productRepository { get; set; }

    public void SaveProduct()
    {
        productRepository?.GetProduct();
        Console.WriteLine("保存ProductService商品成功");
    }
}

public class OrderService : IOrderService
{
    public IOrderRepository orderRepository { get; set; }

    public void GetOrders()
    {
        orderRepository?.GetOrders();
        Console.WriteLine($"查询订单成功, ID: {this.GetHashCode()}");
    }
}

public class ProductRepository : IProductRepository
{
    public void GetProduct()
    {
        Console.WriteLine("获取商品成功");
    }
}

public class OrderRepository : IOrderRepository
{
    public void GetOrders()
    {
        Console.WriteLine("获取订单成功");
    }
}

使用 Autofac 进行批量注入

using Autofac;
using System.Reflection;

public class Program
{
    public static void Main(string[] args)
    {
        // 1、创建ContainerBuilder
        ContainerBuilder containerBuilder = new ContainerBuilder();

        // 1.1、整个项目注册
        containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) // 加载整个项目
                        .AsImplementedInterfaces() // 只要有接口都实现注册
                        .PropertiesAutowired(); // 开发属性依赖注入

        // 2、构造容器
        var container = containerBuilder.Build();

        // 3、取对象
        using (var scope = container.BeginLifetimeScope())
        {
            IProductService productService = scope.Resolve<IProductService>();
            productService.SaveProduct();

            IOrderService orderService = scope.Resolve<IOrderService>();
            orderService.GetOrders();
        }
    }
}

在这个示例中,Autofac 会自动扫描当前程序集中的所有类型,并将实现了接口的类注册为相应的接口。PropertiesAutowired() 方法会自动注入所有实现了接口的属性。

三、 基于特性的对象过滤

有时候,我们希望根据某些条件来注册特定的类型。我们可以使用特性(Attributes)来实现这一点。假设我们希望只注册那些带有 AutoRegisterAttribute 特性的类。

创建特性类

using System;

[AttributeUsage(AttributeTargets.Class)]
public class AutoRegisterAttribute : Attribute
{
}

在类上添加特性

[AutoRegister]
public class ProductService : IProductService
{
    public IProductRepository productRepository { get; set; }

    public void SaveProduct()
    {
        productRepository?.GetProduct();
        Console.WriteLine("保存ProductService商品成功");
    }
}

[AutoRegister]
public class OrderService : IOrderService
{
    public IOrderRepository orderRepository { get; set; }

    public void GetOrders()
    {
        orderRepository?.GetOrders();
        Console.WriteLine($"查询订单成功, ID: {this.GetHashCode()}");
    }
}

public class ProductRepository : IProductRepository
{
    public void GetProduct()
    {
        Console.WriteLine("获取商品成功");
    }
}

public class OrderRepository : IOrderRepository
{
    public void GetOrders()
    {
        Console.WriteLine("获取订单成功");
    }
}

使用 Autofac 进行基于特性的对象过滤

using Autofac;
using System.Reflection;

public class Program
{
    public static void Main(string[] args)
    {
        // 1、创建ContainerBuilder
        ContainerBuilder containerBuilder = new ContainerBuilder();

        // 1.1、整个项目注册
        containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) // 加载整个项目
                        .Where(t => t.GetCustomAttributes(typeof(AutoRegisterAttribute), false).Length > 0) // 通过特性过滤
                        .AsImplementedInterfaces() // 只要有接口都实现注册
                        .PropertiesAutowired(); // 开发属性依赖注入

        // 1.2、注册具体类型接口
        containerBuilder.RegisterType<ProductRepository>().As<IProductRepository>(); // 注入具体类型接口
        containerBuilder.RegisterType<OrderRepository>().As<IOrderRepository>(); // 注入具体类型接口

        // 2、构造容器
        var container = containerBuilder.Build();

        // 3、取对象
        using (var scope = container.BeginLifetimeScope())
        {
            IProductService productService = scope.Resolve<IProductService>();
            productService.SaveProduct();

            IOrderService orderService = scope.Resolve<IOrderService>();
            orderService.GetOrders();
        }
    }
}

在这个示例中,Where(t => t.GetCustomAttributes(typeof(AutoRegisterAttribute), false).Length > 0) 方法会过滤出所有带有 AutoRegisterAttribute 特性的类,并将它们注册到容器中。

四、 基于方法特性的对象过滤

如果你希望根据方法上的特性来过滤类,可以稍微修改一下我们的配置。假设我们希望只注册那些带有 AutoRegisterMethodAttribute 特性方法的类。

创建特性类

using System;

[AttributeUsage(AttributeTargets.Method)]
public class AutoRegisterMethodAttribute : Attribute
{
}

在方法上添加特性

public interface IProductService
{
    void SaveProduct();
}

public interface IOrderService
{
    void GetOrders();
}

public interface IProductRepository
{
    void GetProduct();
}

public interface IOrderRepository
{
    void GetOrders();
}

public class ProductService : IProductService
{
    public IProductRepository productRepository { get; set; }

    public void SaveProduct()
    {
        productRepository?.GetProduct();
        Console.WriteLine("保存ProductService商品成功");
    }
}

public class OrderService : IOrderService
{
    public IOrderRepository orderRepository { get; set; }

    [AutoRegisterMethod]
    public void GetOrders()
    {
        orderRepository?.GetOrders();
        Console.WriteLine($"查询订单成功, ID: {this.GetHashCode()}");
    }
}

public class ProductRepository : IProductRepository
{
    public void GetProduct()
    {
        Console.WriteLine("获取商品成功");
    }
}

public class OrderRepository : IOrderRepository
{
    public void GetOrders()
    {
        Console.WriteLine("获取订单成功");
    }
}

使用 Autofac 进行基于方法特性的对象过滤

using Autofac;
using System.Reflection;

public class Program
{
    public static void Main(string[] args)
    {
        // 1、创建ContainerBuilder
        ContainerBuilder containerBuilder = new ContainerBuilder();

        // 1.1、基于方法特性注册
        containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) // 加载整个项目
                        .Where(t => t.GetMethods().Any(m => m.GetCustomAttributes(typeof(AutoRegisterMethodAttribute), false).Length > 0))
                        .AsImplementedInterfaces() // 只要有接口都实现注册
                        .PropertiesAutowired(); // 开发属性依赖注入

        // 1.2、注册具体类型接口
        containerBuilder.RegisterType<ProductRepository>().As<IProductRepository>(); // 注入具体类型接口
        containerBuilder.RegisterType<OrderRepository>().As<IOrderRepository>(); // 注入具体类型接口

        // 2、构造容器
        var container = containerBuilder.Build();

        // 3、取对象
        using (var scope = container.BeginLifetimeScope())
        {
            // IProductService productService = scope.Resolve<IProductService>();
            // productService.SaveProduct();

            IOrderService orderService = scope.Resolve<IOrderService>();
            orderService.GetOrders();
        }
    }
}

在这个示例中,Where(t => t.GetMethods().Any(m => m.GetCustomAttributes(typeof(AutoRegisterMethodAttribute), false).Length > 0)) 方法会过滤出所有包含带有 AutoRegisterMethodAttribute 特性方法的类,并将它们注册到容器中。

总结

通过本文,学习了如何使用 Autofac 实现依赖注入,包括:

属性注入:使用 PropertiesAutowired() 方法自动注入属性。
批量注入:使用 RegisterAssemblyTypes() 方法自动注册程序集中的所有类型。
基于特性的对象过滤:通过自定义特性类和 GetCustomAttributes() 方法来过滤需要注册的类。
Autofac 提供了灵活的配置选项,可以根据具体需求选择合适的注入方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值