IOC

就是我们需要一个对象 以前我们是去 new 现在我们是直接向 IOC容器 要我们需要的那个对象。

使用一个IOC容器(autofac)通过依赖注入控制各个组件的耦合。也就是说你写好了组件,不需要你去自己控制他们的依赖关系,哪个类又持有哪个类的对象,哪个类里面又要声明一个对象,而是把他们都放到一个容器里面,容器替你做这个(把组件组合起来)。

那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。

DI

由容器动态的将某个依赖关系注入到组件之中 就是 一个对象a 需要去访问数据库 以前我们是自己编写代码去创建一个connction对象 来连接对象,现在我们只需要用@autowrite来获取connection对象,在系统运行时,IOC容器会在合适的时候去创建这个对象,对象a不必关心connection是怎么创建的,何时创建的,这就完成了对各个对象关系的控制

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

谁依赖于谁:当然是 应用程序依赖于IoC容器

为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源

谁注入谁:很明显是 IoC容器注入应用程序某个对象,应用程序依赖的对象

注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

Net Core 三个常用的生命周期

首先,我们想象一个这样一个场景。假设我们有寄快递的需求,那么我们会致电快递公司:“我们要寄快递,派一个快递员过来收货”。接着,快递公司会如何做呢?

  1. 一直派遣同一个快递员来收货。
  2. 第一周派遣快递员A、第二周派遣快递员B收货。
  3. 每次都派遣一个新的快递员收货。

1.Transient(瞬态模式):每一次GetService都会创建一个新的实例   瞬间生命周期 : 每次需要创建一个全新的 每次请求时都会创建的瞬时生命周期服务。这个生命周期最适合轻量级,无状态的服

2.Scoped(作用域模式):在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内) 单例进程唯一实例 :每一次请求都是同一个(多用于时间) 在同作用域,服务每个请求只创建一次。

3.Singleton(单例模式):整个应用程序生命周期内只创建一个实例   全局只创建一次,第一次被请求的时候被创建,然后就一直使用这一个.

如何使用这三种生命周期呢?.我们直接在注入的时候用不同的方法就行了,代码如下:

//注册不同生命周期的服务
services.AddTransient<ITestService, TestService>();
services.AddScoped<ITestService2, TestService2>();
services.AddSingleton<ITestService3, TestService3>();  

自带的IOC 做一些小的项目完全没有问题,但是大项目使用起来就比较单一

IOC容器替换为Autofac

AutoFac生命周期

InstancePerLifetimeScope:作用域模式  在一个嵌套语句块中,只会返回一个实例。 在解决每个生命周期实例作用域组件时,每个嵌套作用域将获得一个实例(例如,每个工作单元)。相当于AddScope

SingleInstance:单例模式,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;相当于AddSingleton

InstancePerDependency:瞬态模式  默认模式,每次调用,都会重新实例化对象;每次请求都创建一个新的对象;AddTransient

Autofac可完美替换系统的依赖注入功能,可实现构造函数注入和属性注入,替换过程:

在Program.cs 新增一行代码

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())//集成Autofac
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

然后在Startup.cs 增加方法

         //集成Autofac
public void ConfigureContainer(ContainerBuilder builder)
{
//添加依赖注入实例,AutofacModuleRegister就继承自Autofac.Module的类
builder.RegisterModule(new StartupHelp.AutofacModuleRegister());
}

ConfigureAutofac 是自己封装的一个类  继承了 Autofac.Module

其中注册类必须继承自Autofac.Module,并且在Load中实现注入,此处应用了程序集范围的注入以及单个对象的注入,最后添加的代码是为了支持控制器的属性注入。

注入的接口(如IUnitOfWork)和实现(UnitOfWork)没有特别。

注入对象的生命周期与.netcore内置的一致

public class AutofacRegister : Autofac.Module
{
#region 单个类和接口
//直接注册某一个类和接口
//左边的是实现类,右边的As是接口
//containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>().SingleInstance();
//这里就跟默认DI差不多
//services.AddScoped<TestServiceE, ITestServiceE>();
#endregion #region 方法1 Load 适用于无接口注入
//var assemblysServices = Assembly.Load("Exercise.Services"); //containerBuilder.RegisterAssemblyTypes(assemblysServices)
// .AsImplementedInterfaces()
// .InstancePerLifetimeScope(); //var assemblysRepository = Assembly.Load("Exercise.Repository"); //containerBuilder.RegisterAssemblyTypes(assemblysRepository)
// .AsImplementedInterfaces()
// .InstancePerLifetimeScope(); #endregion #region 方法2 选择性注入 与方法1 一样
// Assembly Repository = Assembly.Load("Exercise.Repository");
// Assembly IRepository = Assembly.Load("Exercise.IRepository");
// containerBuilder.RegisterAssemblyTypes(Repository, IRepository)
//.Where(t => t.Name.EndsWith("Repository"))
//.AsImplementedInterfaces().PropertiesAutowired(); // Assembly service = Assembly.Load("Exercise.Services");
// Assembly Iservice = Assembly.Load("Exercise.IServices");
// containerBuilder.RegisterAssemblyTypes(service, Iservice)
//.Where(t => t.Name.EndsWith("Service"))
//.AsImplementedInterfaces().PropertiesAutowired();
#endregion #region 方法3 使用 LoadFile 加载服务层的程序集 将程序集生成到bin目录 实现解耦 不需要引用
//获取项目路径
//var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
//var ServicesDllFile = Path.Combine(basePath, "Exercise.Services.dll");//获取注入项目绝对路径
//var assemblysServices = Assembly.LoadFile(ServicesDllFile);//直接采用加载文件的方法
//containerBuilder.RegisterAssemblyTypes(assemblysServices).AsImplementedInterfaces(); //var RepositoryDllFile = Path.Combine(basePath, "Exercise.Repository.dll");
//var RepositoryServices = Assembly.LoadFile(RepositoryDllFile);//直接采用加载文件的方法
//containerBuilder.RegisterAssemblyTypes(RepositoryServices).AsImplementedInterfaces();
#endregion #region 在控制器中使用属性依赖注入,其中注入属性必须标注为public
//public ITestServiceE _testService {get;set }
//注意 上方为属性注入 发现为Null 需要在Startup.cs 的 ConfigureServices 方法下加入如下代码
//services.AddControllers().AddControllersAsServices(); //在控制器中使用属性依赖注入,其中注入属性必须标注为public
// var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
//.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray();
// containerBuilder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
#endregion /// <summary>
/// 当前使用
/// </summary>
/// <param name="builder"></param>
protected override void Load(ContainerBuilder builder)
{
//程序集范围注入 将匹配所有Service结尾的
builder.RegisterAssemblyTypes(typeof(SysUserService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().PropertiesAutowired();
//单个注册 工作单元 和数据库上下文
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().PropertiesAutowired();
builder.RegisterType<dbContext>().As<DbContext>().PropertiesAutowired(); //在控制器中使用属性依赖注入,其中注入属性必须标注为public 就是不需要通过构造函数 直接
//public ITestServiceE _testService {get;set } 可直接_testService.方法 不许在构造函数接收
//注意属性注入 发现为Null 需要在Startup.cs 的 ConfigureServices 方法下加入如下代码
//services.AddControllers().AddControllersAsServices();
var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray();
builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
}
}

然后控制器通过构造函数注入,或者属性注入测试

ASP.NET Core 3.1 IOC容器以及默认DI以及替换Autofac生命周期的更多相关文章

  1. Asp.Net Core 内置IOC容器的理解

    Asp.Net Core 内置IOC容器的理解 01.使用IOC容器的好处 对接口和实现类由原来的零散式管理,到现在的集中式管理. 对类和接口之间的关系,有多种注入模式(构造函数注入.属性注入等). ...

  2. [ASP.NET Core 3框架揭秘] 依赖注入[8]:服务实例的生命周期

    生命周期决定了IServiceProvider对象采用怎样的方式提供和释放服务实例.虽然不同版本的依赖注入框架针对服务实例的生命周期管理采用了不同的实现,但总的来说原理还是类似的.在我们提供的依赖注入 ...

  3. 简单讲解Asp.Net Core自带IOC容器ServiceCollection

    一.  理解ServiceCollection之前先要熟悉几个概念:DIP.IOC.DI.Ioc容器: 二.  接下来先简单说一下几个概念问题: 1.DIP(依赖倒置原则):六大设计原则里面一种设计原 ...

  4. [IoC容器Unity]第二回:Lifetime Managers生命周期

    1.引言 Unity的生命周期是注册的类型对象的生命周期,而Unity默认情况下会自动帮我们维护好这些对象的生命周期,我们也可以显示配置对象的生命周期,Unity将按照配置自动管理,非常方便,下面就介 ...

  5. [转载][IoC容器Unity]第二回:Lifetime Managers生命周期

    1.引言 Unity的生命周期是注册的类型对象的生命周期,而Unity默认情况下会自动帮我们维护好这些对象的生命周期,我们也可以显示配置对象的生命周期,Unity将按照配置自动管理,非常方便,下面就介 ...

  6. ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自带的IOC容器)

    前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...

  7. ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)

    前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...

  8. ASP.NET Core中使用IOC三部曲(三.采用替换后的Autofac来实现AOP拦截)

    前言 本文主要是详解一下在ASP.NET Core中,采用替换后的Autofac来实现AOP拦截 觉得有帮助的朋友~可以左上角点个关注,右下角点个推荐 这里就不详细的赘述IOC是什么 以及DI是什么了 ...

  9. .net core系列之《.net core内置IOC容器ServiceCollection》

    一.IOC介绍 IOC:全名(Inversion of Control)-控制反转 IOC意味着我们将对象的创建控制权交给了外部容器,我们不管它是如何创建的,我们只需要知道,当我们想要某个实例时,我们 ...

随机推荐

  1. kafka入门之broker--日志存储设计

    kafaka并不是直接将原省消息写入日志文件的,相反,它会将消息和一些必要的元数据信息大宝在一起封装成一个record写入日志.其实就是我们之前介绍的batch 具体对每个日志而言,kafka又将其进 ...

  2. oracle set oracle_sid=xxxxxx

    本地有多个实例,在cmd  输入  set oracle_sid=xxxxx   来指定要连接的实例 sqlplus xxxx/xxxx@1.1.1.1.1/sid   连接数据库

  3. JZOJ 11.21 提高B组反思

    JZOJ 11.21 提高B组反思 T1 第二类斯特林数 直接套公式 \(S(i,j)=S(i-1,j-1)+S(i-1,j)*j\) 由于过大,\(unsigned\ long\ long\)都存不 ...

  4. AOV图与拓扑排序&AOE图与关键路径

    AOV网:所有的工程或者某种流程可以分为若干个小的工程或阶段,这些小的工程或阶段就称为活动.若以图中的顶点来表示活动,有向边表示活动之间的优先关系,则这样活动在顶点上的有向图称为AOV网. 拓扑排序算 ...

  5. Markdown实用教程

    Markdown 是用来编写结构化文档的一种纯文本格式,它使我们在双手不离开键盘的情况下,可以对文本进行一定程度的格式排版.markdown语法是通用的,很多写作平台都是支持markdown的,比如简 ...

  6. 基础篇:JAVA.Stream函数,优雅的数据流操作

    前言 平时操作集合数据,我们一般都是for或者iterator去遍历,不是很好看.java提供了Stream的概念,它可以让我们把集合数据当做一个个元素在处理,并且提供多线程模式 流的创建 流的各种数 ...

  7. 在Python中使用moviepy进行音视频剪辑混音合成时输出文件无声音问题

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在使用moviepy进行音视频剪辑时发现输出成功但 ...

  8. PyQt开发案例:结合QDial实现的QStackedWidget堆叠窗口程序例子及完整代码

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.案例说明 本案例是老猿在学习QStackedWidget中的一个测试案例,该案例使用QStack ...

  9. 孪生网络入门(下) Siamese Net分类服装MNIST数据集(pytorch)

    主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, gr ...

  10. vue项目中增加打印功能

    export default function printFile(html) { let userAgent = navigator.userAgent; if ( (userAgent.index ...