一、配置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. V8 编译浅谈

    ​简介:本文是一个 V8 编译原理知识的介绍文章,旨在让大家感性的了解 JavaScript 在 V8 中的解析过程. ​ 作者 | 子弈 来源 | 阿里技术公众号 一 简介 本文是一个 V8 编译原 ...

  2. dotnet 读 WPF 源代码笔记 WriteableBitmap 的渲染和更新是如何实现

    在 WPF 框架提供方便进行像素读写的 WriteableBitmap 类,本文来告诉大家在咱写下像素到 WriteableBitmap 渲染,底层的逻辑 之前我使用 WriteableBitmap ...

  3. 2019-8-31-dotnet-线程静态字段

    title author date CreateTime categories dotnet 线程静态字段 lindexi 2019-08-31 16:55:58 +0800 2019-06-13 0 ...

  4. 视频讲解如何构建surging微服务调用

    surging 是一款优秀的微服务引擎,包括了社区版,标准版,异构版,平台版本来解决公司的业务场景需求,如果你是初学者,或者是技术狂热者,社区版完全可以符合你们的要求来学习或者构建起微服务体系的引擎框 ...

  5. 第三章-常用的渗透测试工具-(sqlmap)

    常用渗透测试工具 1.sqlmap 支持的数据库:MySQL.Oracle.PostgreSQL.SQL Server.Access.IBM DB2.SQLite.Firebird.Sybase.SA ...

  6. 记一次线上Redis内存占用过高、大Key问题的排查

    问题背景 在一个风和日丽的下午,公司某项目现场运维同学反馈,生产环境3个Redis的Sentinel集群节点内存占用都很高,达到了17GB的内存占用量. 稍加思索,应该是某些Key的Value数据体量 ...

  7. 超级简单实用的CSS3动画,增添网页效果

    有时候做网页,如果都写成静态的没有动态效果,犹如一张张图片,没有视觉感受,没有达到很好的视觉效果. 其实一些简单的CSS3动画,可以增添网页的动态感,使自己设计的网页更有视觉享受.1.图片有一定角度的 ...

  8. 如此丝滑的API设计,用起来真香

    分享是最有效的学习方式. 博客:https://blog.ktdaddy.com/ 故事 工位上,小猫一边撸着代码,一边吐槽着前人设计的接口. 如下: "我艹,货架模型明明和商品SKU模型是 ...

  9. diffusion model(一):DDPM技术小结 (denoising diffusion probabilistic)

    发布日期:2023/05/18 主页地址:http://myhz0606.com/article/ddpm 1 从直觉上理解DDPM 在详细推到公式之前,我们先从直觉上理解一下什么是扩散 对于常规的生 ...

  10. 【题解】A18536.星光交错的律动

    题目跳转 思路:这道题可能跟博弈论有一点关系,没有学习过博弈论做起来应该问题也不大.思考一个问题,先手必胜的前提是什么? 有关更多的内容可以前往:浅谈有向无环图 先手必胜的前提是,在任何一种局面下,先 ...