深入浅出:从零开始掌握 Autofac 的依赖注入技巧

embedded/2025/3/3 5:43:14/

目录

Autofac%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8-toc" name="tableOfContents" style="margin-left:80px">Autofac基本使用

构造函数注入使用

属性注入使用

方法注入使用

AOP扩展使用

Autofac%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8" name="Autofac%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8" style="background-color:transparent">Autofac基本使用

Autofac:是一个用于.NET应用程序的依赖注入(Dependency Injection,DI)容器,旨在通过控制对象的生命周期和依赖关系来促进松耦合、可测试和可扩展的代码结构,其官方文档:地址 :

使用Autofac首先需要在项目中进行安装,可以通过NuGet包管理器来安装,如下所示,接下来就开始对Autofac的基本使用方法来概述:

创建接口和实体类:首先定义需要依赖注入的接口和对应的实现类,如下所示:

namespace webapi_study.Common
{public interface IDatabaseConnection{void Connect();}public class DatabaseConnection : IDatabaseConnection{public void Connect(){Console.WriteLine("Connected to the database.");}}
}

配置Autofac容器:创建一个Autofac容器来注册服务并在应用程序中使用依赖注入,如下所示:

namespace webapi_study.Common
{public class AutofacTest{public static void Register(){// 01、创建容器构建器对象var builder = new ContainerBuilder();// 02、注册服务组件builder.RegisterType<DatabaseConnection>().As<IDatabaseConnection>();// 03、构建容器var container = builder.Build();// 04、解析服务var service = container.Resolve<IDatabaseConnection>();service.Connect();  // 输出: "Connected to the database."}}
}

然后在入口文件处调用我们的注册服务,可以看到日志中打印了我们的数据:

如果想同时注册多个服务的话,可以为多个不同的接口注册不同的实现:

构造函数注入使用

Autofac中构造函数注入是最常见的依赖注入方式之一,通过构造函数注入Autofac会自动解析类构造函数中需要的依赖并将其注入到类的实例中,下面是如何通过构造函数注入来实现依赖注入的示例:

构造函数注入:首先我们创建一个类,它有一个需要注入的依赖项:

namespace webapi_study.Common
{public interface IServiceA{void Execute();}public class ServiceA : IServiceA{public void Execute(){Console.WriteLine("ServiceA is running!");}}public class Consumer{private readonly IServiceA _serviceA;// 通过构造函数注入public Consumer(IServiceA serviceA){_serviceA = serviceA;}public void Run(){_serviceA.Execute();}}
}

注册服务并注入解析:接下来我们使用Autofac注册ServiceA和Consumer并通过构造函数注入来自动解析IServiceA,如下所示:

namespace webapi_study.Common
{public class AutofacTest{public static void Register(){// 01、创建容器构建器对象var builder = new ContainerBuilder();// 02、注册多个服务组件builder.RegisterType<ServiceA>().As<IServiceA>();builder.RegisterType<Consumer>(); // 注册Consumer(它会自动通过构造函数注入IServiceA)// 03、构建容器var container = builder.Build();// 04、解析服务var consumer = container.Resolve<Consumer>();consumer.Run();}}
}

然后可以看到我们打印的语句仍然被执行了:

多个构造函数的注入:如果类有多个构造函数Autofac默认会注入参数最多的构造函数:

public class ConsumerWithMultipleConstructors
{private readonly IServiceA _serviceA;private readonly string _message;// 构造函数1public ConsumerWithMultipleConstructors(IServiceA serviceA){_serviceA = serviceA;_message = "Default Message";}// 构造函数2public ConsumerWithMultipleConstructors(IServiceA serviceA, string message){_serviceA = serviceA;_message = message;}public void Run(){Console.WriteLine(_message);_serviceA.Execute();}
}

如果希望明确指定使用某个构造函数,可以使用WithParameter或者WithParameters方法来指定构造函数的参数,如下所示: 

builder.RegisterType<ServiceA>().As<IServiceA>();
builder.RegisterType<ConsumerWithMultipleConstructors>().WithParameter("message", "Custom Message");var container = builder.Build();
var consumer = container.Resolve<ConsumerWithMultipleConstructors>();
consumer.Run();
// 输出:
// "Custom Message"
// "ServiceA is running!"

属性注入使用

属性注入:是依赖注入的另一种方式,其中依赖关系通过对象的属性而不是构造函数来注入,这种方式在某些场景下很有用,尤其是当你不能修改构造函数的情况下或者依赖关系可以在对象创建后注入。在Autofac中属性注入可以通过InjectProperties方法来实现,它允许在实例化对象后自动注入属性依赖,首先创建一个需要依赖注入的类并使用属性来接收依赖项:

public interface IServiceA
{void Execute();
}
public class ServiceA : IServiceA
{public void Execute(){Console.WriteLine("ServiceA is running!");}
}
public class Consumer
{public IServiceA ServiceA { get; set; }  // 通过属性注入依赖public void Run(){ServiceA.Execute();}
}

注册和属性注入:接下来使用Autofac注册服务并使用InjectProperties来进行属性注入,其中的方法PropertiesAutowired会告诉Autofac自动注入属性,如果Consumer类中有一个公共属性Autofac会查找并自动注入它,如下所示:

var builder = new ContainerBuilder();
// 注册 `IServiceA` 与 `ServiceA`
builder.RegisterType<ServiceA>().As<IServiceA>();
// 注册 `Consumer` 并启用属性注入
builder.RegisterType<Consumer>().PropertiesAutowired();
var container = builder.Build();
// 从容器中解析 `Consumer`
var consumer = container.Resolve<Consumer>();
// 使用 `Consumer` 的 `Run` 方法
consumer.Run();  // 输出: "ServiceA is running!"

适用场景

1)懒加载依赖:你可以在对象创建后再注入依赖,而不是在构造时立即注入

2)可选依赖:某些依赖关系不是每次都需要的,或者可以在对象初始化后再注入

3)类的设计:如果你不能修改类的构造函数,可以考虑使用属性注入

方法注入使用

方法注入:是一种依赖注入的方式通过方法参数将依赖关系注入到类中而不是通过构造函数或属性,方法注入通常用于将依赖关系传递给需要的具体方法而不是整个类,在Autofac中方法注入可以通过使用WithParameter或OnActivated等方式来实现,如下:

定义服务和需要注入依赖的方法:假设你有一个类Consumer它需要一个服务IServiceA并通过方法来注入这个依赖:

public interface IServiceA
{void Execute();
}
public class ServiceA : IServiceA
{public void Execute(){Console.WriteLine("ServiceA is running!");}
}
public class Consumer
{public void Run(IServiceA serviceA)  // 依赖注入通过方法参数传入{serviceA.Execute();}
}

接下来使用Autofac配置和注册这些类,在解析Consumer时我们将IServiceA作为参数传递给Run方法,最后通过容器解析Consumer并手动调用Run方法同时传递需要的IServiceA实例:

var builder = new ContainerBuilder();// 注册 IServiceA 和 ServiceA
builder.RegisterType<ServiceA>().As<IServiceA>();// 注册 Consumer
builder.RegisterType<Consumer>();var container = builder.Build();// 从容器中解析 Consumer 实例
var consumer = container.Resolve<Consumer>();// 手动注入 IServiceA 到 Run 方法
var serviceA = container.Resolve<IServiceA>();
consumer.Run(serviceA);  // 输出: "ServiceA is running!"

另外Autofac也支持通过OnActivated来在对象激活后注入方法依赖,这种方式是在对象创建后自动执行某些方法:

builder.RegisterType<Consumer>().OnActivated(e =>{var serviceA = e.Context.Resolve<IServiceA>();e.Instance.Run(serviceA);  // 依赖注入到方法});

适用场景

1)临时依赖关系:如果某些依赖只在特定方法调用时才需要,可以使用方法注入
2)不需要全局依赖的场景:在某些任务处理方法中注入特定的服务而不需要为整个类注入
3)灵活控制依赖生命周期:方法注入可以更灵活地控制依赖注入的时机和范围

AOP扩展使用

Autofac中AOP(面向切面编程)主要通过拦截器来实现,AOP允许在不修改原始代码的情况下在方法执行前后进行处理,比如日志记录、性能监控、事务管理等,Autofac通过Intercept方法和IDisposable接口的实现来提供对方法的拦截从而实现AOP的功能,AOP实现步骤如下:

创建一个拦截器:拦截器是实现AOP的核心,它允许你定义在方法执行前后或抛出异常时的处理逻辑,拦截器实现了IInterceptor接口:

using Castle.DynamicProxy;public class MyInterceptor : IInterceptor
{public void Intercept(IInvocation invocation){// 在方法调用前执行Console.WriteLine("Before method call");// 执行实际方法invocation.Proceed();// 在方法调用后执行Console.WriteLine("After method call");}
}

定义目标接口和实现:需要定义一个接口和实现,拦截器将会拦截这个接口的方法:

public interface IMyService
{void DoWork();
}public class MyService : IMyService
{public void DoWork(){Console.WriteLine("Doing work...");}
}

注册拦截器和目标类型:通过Autofac注册类型并指定拦截器,在Autofac中可以使用InterceptedBy方法来指定拦截器,最后使用容器解析目标对象时拦截器将自动被应用:

var builder = new ContainerBuilder();// 注册 MyInterceptor
builder.RegisterType<MyInterceptor>();// 注册目标类型并应用拦截器
builder.RegisterType<MyService>().As<IMyService>().EnableInterfaceInterceptors().InterceptedBy(typeof(MyInterceptor));var container = builder.Build();
var service = container.Resolve<IMyService>();
service.DoWork();  // 输出: Before method call -> Doing work... -> After method call

AOP的生命周期管理Autofac支持通过生命周期管理来确保拦截器或被拦截的服务的生命周期符合你的需求,比如可以使用InstancePerLifetimeScope来确保在同一个生命周期中使用相同的实例:

builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope()  // 控制生命周期.EnableInterfaceInterceptors().InterceptedBy(typeof(MyInterceptor));

常见的AOP用法

1)日志记录:在方法执行前后记录日志。
2)事务管理:在方法执行前开始事务,方法执行后提交事务。
3)性能监控:记录方法执行时间。
4)权限检查:在方法执行前检查权限。


http://www.ppmy.cn/embedded/169539.html

相关文章

智能图像处理平台:图像处理配置类

这里我们先修改一下依赖&#xff0c;不用JavaCV&#xff0c;用openCV。 导入依赖&#xff1a; <!-- JavaCV 依赖&#xff0c;用于图像和视频处理 --> <!-- <dependency>--> <!-- <groupId>org.bytedeco</groupId>--> &l…

SSH密码更改

Windows User目录下的.ssh/config&#xff0c;全部删除 linux 在主用户文件夹&#xff0c;ctrlh显示隐藏文件。删除.shh文件夹内所有文件。

2025机械考研复试面试问题汇总篇(含13门科目),考研机械复试专业面试常见重点问题总结!考研机械复试专业面试准备看这一篇就够了!

前言——25机械考研复试专业面试问题汇总 机械复试超全流程攻略 机械复试看这一个专栏就够用了!机械复试调剂英语自我介绍口语专业面试常见问题总结 机械保研面试-CSDN博客https://blog.csdn.net/weixin_56510835/article/details/143101233 本专栏包含的所有文章内容,可以看…

《Effective Objecti-C 2.0》第二章阅读笔记

小蓝书学习 第二章&#xff1a;对象&#xff0c;消息&#xff0c;运行期前言第六条&#xff1a;理解“属性”这一概念属性特质原子性atomicnonatimic 读写权限内存管理语义方法名 第七条&#xff1a;在对象内部进来直接访问变量实例第八条&#xff1a;理解“对象等同性”这一概…

如何配置HTTP代理及SOCKS代理的工作原理

目录 一、HTTP代理的配置与应用 二、SOCKS代理的工作原理与应用 三、HTTP代理与SOCKS代理的比较 四、总结 在探讨如何配置HTTP代理以及SOCKS代理的工作原理时&#xff0c;我们将通过简洁的语言、具体的代码示例和实际案例&#xff0c;为您呈现一个清晰、易懂的理解框架。 …

Ruby基础

一、字符串 定义 283.to_s //转为string "something#{a}" //定义字符串&#xff0c;并且插入a变量的值 something//单引号定义变量 %q(aaaaaaaaa) // 定义字符串&#xff0c;&#xff08;&#xff09;内可以是任何数&#xff0c;自动转义双引号%Q("aaaaa"…

记录一次MQTT慢订阅优化

场景&#xff1a;收不到设备数据&#xff0c;MQTT监控&#xff0c;发现真实数据确实没有&#xff0c;监听2个小时&#xff0c;获取大量慢订阅信息 优化方式 通配符匹配加速​ 优化订阅主题匹配算法&#xff0c;实现多级哈希索引结构。例如将home//status拆分为固定层级匹配&am…

南京来可电子CAN总线数据记录仪在汽车售后服务站的应用

南京来可电子CAN总线数据记录仪在汽车售后服务站的应用 南京来可电子&#xff08;LaiCore&#xff09;作为国内领先的车载数据采集设备供应商&#xff0c;其CAN总线数据记录仪凭借高精度、多协议兼容性及智能化功能&#xff0c;在汽车售后服务站中发挥重要作用。以下是其核心应…