一、配置Autofac替换内置DI

1.安装Nuget包:Autofac,Autofac.Extensions.DependencyInjection

2.Program.cs中CreateHostBuilder方法后加上.UseServiceProviderFactory(new AutofacServiceProviderFactory()) ; 告诉程序要使用Autofac。

3.Startup.cs中增加方法ConfigureContainer(ContainerBuilder containerBuilder),实例注入的地方,配置完成。

 /// <summary>
/// Autofac注册服务的地方,Autofac会自动调用
/// </summary>
/// <param name="containerBuilder"></param>
public void ConfigureContainer(ContainerBuilder containerBuilder)
{ }

二、构造函数注入

新建IUserService,类UserService,控制器UserController

 public interface IUserService
{
public string GetUserName();
}
 public class UserService
{
public string GetUserName()
{
return "张三";
}
}
 public class UserController : Controller
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
public IActionResult Index()
{
string name = _userService.GetUserName();
return Content(name);
}
}

在上面的ConfigureContainer方法把UserService注入进来,默认是瞬时注入

瞬时注入:containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency();;

单例注入:containerBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance();

生命周期注入: containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();

 /// <summary>
/// Autofac注册服务的地方,Autofac会自动调用
/// </summary>
/// <param name="containerBuilder"></param>
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
//注册服务
containerBuilder.RegisterType<UserService>().As<IUserService>();
}

访问/User/Index,_userService成功注入,正确获取结果。

三、属性注入

1.把UserController改成属性注入形式,属性注入有一个问题,就是那些属性需要注入?全部注入没必要,父类也有很多属性,要按需注入,给属性增加一个自定义特性标识说明需要注入。

 public class UserController : Controller
{
[AutowiredProperty]
private IUserService userService { get; set; }
public IActionResult Index()
{
string name = userService.GetUserName();
return Content(name);
}
}

2.新增自定义特性类AutowiredPropertyAttribute.cs

[AttributeUsage(AttributeTargets.Property)]//为了支持属性注入,只能打到属性上
public class AutowiredPropertyAttribute : Attribute
{
}

3.增加识别特性类AutowiredPropertySelector.cs

 /// <summary>
/// IPropertySelector:查看属性上是否标记某一个特性
/// </summary>
public class AutowiredPropertySelector : IPropertySelector
{
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
//判断属性的特性是否包含自定义的属性,标记有返回true
return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));
}
}

4.因为Controller 默认是由 Mvc 模块管理的,需要把控制器放到IOC容器中,在Startup.cs的ConfigureServices中增加

 //让控制器实例由容器创建
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

5.把容器注册到IOC容器,在Startup.cs的ConfigureContainer()增加

 //获取所有控制器类型并使用属性注入
Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());

6.验证结果,新增一个接口IOrderService.cs和一个实现类OrderService.cs做对比

 public interface IOrderService
{
public string CreateOrder();
} public class OrderService : IOrderService
{
public string CreateOrder()
{
return "下单成功";
}
}

把UserController改成

  public class UserController : Controller
{
[AutowiredProperty]
private IUserService userService { get; set; } private IOrderService orderService { get; set; }//不加属性注入标识
public IActionResult Index()
{
string name = userService.GetUserName();
return Content(name);
}
}

注入方法ConfigureContainer()增加

containerBuilder.RegisterType<OrderService>().As<IOrderService>();

运行程序,能看到增加了注入标识的userService注入成功,没加标识的orderService没有注入。

四、批量注入

实际项目中那么多需要注入的类,一个个写注册就不太现实了,需要一个可以批量注入的方法。

1.新建三个空接口IScopeDenpendency.cs,ISingletonDenpendency.cs,ITransitDenpendency.cs

  /// <summary>
/// 瞬时注入
/// </summary>
public interface ITransitDenpendency
{
}
  /// <summary>
/// 单例注入标识
/// </summary>
public interface ISingletonDenpendency
{
}
   /// <summary>
/// 生命周期注入标识
/// </summary>
public interface IScopeDenpendency
{
}

2.把上面要注入的类实现上面的接口

3.新增一个IocManger类

  /// <summary>
/// 批量注入扩展
/// </summary>
/// <param name="builder"></param>
/// <param name="assembly"></param>
public static void BatchAutowired(this ContainerBuilder builder, Assembly assembly)
{ var transientType = typeof(ITransitDenpendency); //瞬时注入
var singletonType = typeof(ISingletonDenpendency); //单例注入
var scopeType = typeof(IScopeDenpendency); //单例注入
//瞬时注入
builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(transientType))
.AsSelf()
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired(new AutowiredPropertySelector());
//单例注入
builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(singletonType))
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired(new AutowiredPropertySelector());
//生命周期注入
builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(scopeType))
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired(new AutowiredPropertySelector()); }

4.把注入类ConfigureContainer改成

 /// <summary>
/// Autofac注册服务的地方,Autofac会自动调用
/// </summary>
/// <param name="containerBuilder"></param>
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
//获取所有控制器类型并使用属性注入
Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector()); //批量自动注入,把需要注入层的程序集传参数
containerBuilder.BatchAutowired(typeof(UserService).Assembly);
containerBuilder.BatchAutowired(typeof(UserRepository).Assembly);
}

5.防止startup.cs代码过多,建一个Module把注入代码搬走,新建AutofacRegisterModule.cs类把ConfigureContainer的代码移过去

 public class AutofacRegisterModule:Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
//获取所有控制器类型并使用属性注入
Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector()); //批量自动注入,把需要注入层的程序集传参数
builder.BatchAutowired(typeof(UserService).Assembly);
builder.BatchAutowired(typeof(UserRepository).Assembly);
}
}

ConfigureContainer的代码变成

/// <summary>
/// Autofac注册服务的地方,Autofac会自动调用
/// </summary>
/// <param name="containerBuilder"></param>
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterModule<AutofacRegisterModule>();
}

五、手动获取实例

手动获取实例的场景有静态帮助类中获取实例,例如redisHelper中获取注入的配置文件中的连接字符串

1.在上面的IocManager类中增加

 private static object obj = new object();
private static ILifetimeScope _container { get; set; } public static void InitContainer(ILifetimeScope container)
{
//防止过程中方法被调用_container发生改变
if (_container == null)
{
lock (obj)
{
if (_container == null)
{
_container = container;
}
}
}
}
/// <summary>
/// 手动获取实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Resolve<T>()
{
return _container.Resolve<T>();
}

2.在Startup.cs的Configure()中增加

//获取Autofac容器上下文信息
IocManager.InitContainer(app.ApplicationServices.GetAutofacRoot());

3.验证,新建一个DataHelper.cs类

 public class DataHelper
{
//手动注入UserService
private static IUserService userService = IocManager.Resolve<IUserService>();
public static string GetData()
{
return userService.GetUserName();
}
}

修改UserController用DataHelper的方法成功获取数据

六、其它用法

1.不用接口,直接注入实例

 public class UserService :ITransitDenpendency
{
public string GetUserName()
{
return "张三";
}
}

2.一接口多实现

 public class UserService :IUserService
{
public string GetUserName()
{
return "张三";
}
} public class User2Service : IUserService
{
public string GetUserName()
{
return "张三2号";
}
}

最后:源码地址:https://github.com/weixiaolong325/.NetCore5.0AutofacDemo

演示项目结构:

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用的更多相关文章

  1. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  2. ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下

    先简单了解一这个几个 名词的意思. 控制反转(IOC) 依赖注入(DI) 并不是某种技术. 而是一种思想.一种面向对象编程法则 什么是控制反转(IOC)?  什么是依赖注入(DI) 可以点击下面链接 ...

  3. ASP.NET Core 在 JSON 文件中配置依赖注入

    前言 在上一篇文章中写了如何在MVC中配置全局路由前缀,今天给大家介绍一下如何在在 json 文件中配置依赖注入. 在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等 ...

  4. 转载:ASP.NET Core 在 JSON 文件中配置依赖注入

    在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等)时候,都是提供了专有的接口以供使用第三方的依赖注入组件,比如我们常用的会使用 Autofac.Untiy.Stri ...

  5. ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings

    问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...

  6. 从零开始,搭建博客系统MVC5+EF6搭建框架(2),测试添加数据、集成Autofac依赖注入

    一.测试仓储层.业务层是否能实现对数据库表的操作 1.创建IsysUserInfoRepository接口来继承IBaseRepository父接口 namespace Wchl.WMBlog.IRe ...

  7. .NET CORE——Console中使用依赖注入

    我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...

  8. 如何在.NET Core控制台程序中使用依赖注入

    背景介绍 依赖注入(Dependency Injection), 是面向对象编程中的一种设计原则,可以用来减低代码之间的耦合度.在.NET Core MVC中 我们可以在Startup.cs文件的Co ...

  9. 【干货】利用MVC5+EF6搭建博客系统(二)测试添加数据、集成Autofac依赖注入

    PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.测试仓储层.业务层是否能实现对数据库表的操作 1.在52MVCBlog.IRepository程序集下创建IsysUserInf ...

  10. 在C#中使用依赖注入

    依赖注入(Dependency Injection,缩写为DI)是一种实现(Inversion of Control,缩写为IoC)的方法.在编写C#代码时,使用这种方法能够解决一些场景的需求.本系列 ...

随机推荐

  1. 前沿分享|阿里云数据库资深技术专家 姚奕玮:AnalyticDB MySQL离在线一体化技术揭秘

    ​简介: 本篇内容为2021云栖大会-云原生数据仓库AnalyticDB技术与实践峰会分论坛中,阿里云数据库资深技术专家 姚奕玮关于"AnalyticDB MySQL离在线一体化技术揭秘&q ...

  2. 7张图揭晓RocketMQ存储设计的精髓

    ​简介: RocketMQ 作为一款基于磁盘存储的中间件,具有无限积压能力,并提供高吞吐.低延迟的服务能力,其最核心的部分必然是它优雅的存储设计. 存储概述 RocketMQ 存储的文件主要包括 Co ...

  3. DLF +DDI 一站式数据湖构建与分析最佳实践

    简介: 本文由阿里云数据湖构建 DLF 团队和 Databricks 数据洞察团队联合撰写,旨在帮助您更深入地了解阿里云数据湖构建(DLF)+Databricks 数据洞察(DDI)构建一站式云上数据 ...

  4. [ELK] 生产环境中 Elasticsearch 的重要配置项

    配置 Elasticsearch https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html 重要的 E ...

  5. WPF 对接 Vortice 调用 D2D 使用 IWICBitmap 离屏渲染

    通过 Vortice 库可以使用非常底层的方式调用到 Direct2D1 进行渲染,本文将使用 D2D 离屏渲染到 IWICBitmap 上,再使用一点点反射黑科技,直接将此 IWICBitmap 对 ...

  6. linux安装nvm和node

    linux安装nvm和node 一.环境 debian10 nodejs 二.安装 2.1 安装NVM 运行以下命令下载并运行 NVM 安装脚本: curl https://raw.githubuse ...

  7. 七、Doris Colocation Join

    Colocation Join 是在 Doris 0.9 版本中引入的新功能.旨在为某些 Join 查询提供本地性优化,来减少数据在节点间的传输耗时,加速查询. 1.基本理论 Join 的常见连接类型 ...

  8. GOLANG-配置nginx反向代理端口 配置域名

    目录 配置/etc/nginx/nginx.conf文件 新建/etc/nginx/conf.d/doc.haimait.conf文件 重启nginx服务 解析自己的域名到服务器的公网ip 配置/et ...

  9. MQTT的使用一

    MQTT:物联网消息传递标准 简介 MQTT是用于物联网(IoT)的OASIS标准消息传递协议.它被设计为一种非常轻量级的发布/订阅消息传送,非常适合以较小的代码占用量和最小的网络带宽连接远程设备.如 ...

  10. three.js 物体要使用光线投射技术,计算是否点击位置与物体有交叉

    原生 DOM 还用原生的 DOM 点击事件,要注意开启 pointerEvents CSS3DRenderer 是一个新的渲染器,需要在渲染循环调用并适配 labelRenderer.domEleme ...