当前位置: 首页 > news >正文

使用 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、创建ContainerBuilderContainerBuilder 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、创建ContainerBuilderContainerBuilder 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、创建ContainerBuilderContainerBuilder 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、创建ContainerBuilderContainerBuilder 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 提供了灵活的配置选项,可以根据具体需求选择合适的注入方式。

http://www.xdnf.cn/news/170911.html

相关文章:

  • 嵌入式软件--stm32 DAY 4 中断系统
  • Linux日志处理命令多管道实战应用
  • Python爬虫实战:获取网yi云音乐飙升榜的歌曲数据并作分析,为歌单推荐做参考
  • Spark SQL核心概念与编程实战:从DataFrame到DataSet的结构化数据处理
  • 《一键式江湖:Docker Compose中间件部署108式》开篇:告别“配置地狱”,从此笑傲云原生武林!》
  • python+adafruit_pca9685 测试舵机存储当前角度
  • 知识体系_数据量纲化处理方式
  • PWN基础-利用格式化字符串漏洞泄露canary结合栈溢出getshell
  • 神经网络笔记 - 神经网络
  • 东田数码科技前端面经
  • 运算符分为哪几类?哪些运算符常用作判断?简述运算符的优先级
  • 电池的寿命
  • 参数规模:衡量大语言模型体量的标尺
  • 【Java面试笔记:进阶】23.请介绍类加载过程,什么是双亲委派模型?
  • NEPCON China 2025 | 具身智能时代来临,灵途科技助力人形机器人“感知升级”
  • Spring MVC深度解析:从原理到实战
  • 进程与线程-----C语言经典题目(8)
  • Net版本Spire.doc 最新版去水印
  • OpenCV进阶操作:图像金字塔
  • Django(快速上手版)
  • IDEA中使用Git
  • 物联网相关
  • 【仿Mudou库one thread per loop式并发服务器实现】服务器边缘测试+性能测试
  • 强制缓存vs协商缓存
  • pycharm无法创建venv虚拟环境
  • Web安全:威胁解析与综合防护体系构建
  • 快速排序及其在Unity游戏开发中的应用
  • Node.js API 安全的主要策略:最佳实践
  • 面试记录1-春招补录0427
  • 【Hive入门】Hive基础操作与SQL语法:DML操作全面解析