第四节 .NetCore框架中的默认依赖注入

.NetCore框架在开发设计之初,就把控制反转(Inversion of Control,缩写为IoC)作为该框架的一个重要的开发设计思想,并通过在框架中集成依赖注入(DI)容器的默认实现等技术和手段表现并实施了这个开发设计思想。.NETCore团队对依赖注入的实现贯穿整个ASP.NET Core框架的整个项目中,它的实现被定义在Microsoft.Extensions.DependencyInjection类中。

       所以.NetCore框架不是要必需通过第三方的依赖注入容器(Autofac)或MEF(Managed Extensibility Framework(托管可扩展框架)) 实现依赖注入技术,只需要通过默认提供依赖注入(DI)容器使开发者即在工程中即可实现依赖注入技术,通过这个技术体现控制反转的开发设计思想。简单来说通过new关键字来给对象进行赋值操作的是“控制转”,即对象的初始化操作依赖于类所定义的实现;不管使用的是默认依赖注入容器、Autofac或MEF等技术和手段,只要开发者在程序中使用了这些技术和手段进行,那么他就遵循了控制反转的开发思想,至于程度的深浅和效果的好坏,只有靠开发者对设计思想理解的程度和开发技术使用的灵活性了。对象的初始化操作依赖于接口中的声明,即为“控制转”。对象的初始化与接口的声明相直接关联,与具体的实现不再直接关联,如果结合泛型或对程序集的“依赖查找”(Dependency Lookup)等技术,对象可以被接口极其方便和极低成本的初始化为不同的类型实例,不同的操作过程,甚至不同的持久化目标(即数据库)。

       控制反转思想和依赖注入技术的作用除了降低耦合,使用程序更容易移植和复用外。在中间件在行其道的今天,在一个工程中使用3—5个中间件再正常不过。如果中间件都按照控制反转思想和依赖注入技术的标准进行开发,由于易移植和复用的方便和极低的成本,一个及其重要但被大多数开发者所忽略的作用,可用于易移植和复用的代码和中间件的存量将会大大增加。实际上这种趋势在当今的开发中已经开始显现。不要重复造轮子是程序开发的一个极其重要的原则,它有层含义:1、泛型、委托和事件的使用从代码段和类的量级上极其有效的减少了实现同样功能的重复代码。2、控制反转思想和依赖注入技术和开源从项目、工程、中间件、甚至框架的量级上,开发者可以极其方便、极低成本和安全可控的使用第三方所提供的代码,而不是开发者自己开发功能相似的代码。实际上只要第三方所提供的代码只要版本在3或者以上,各个方面的性能都有100%的可能性比开发者自己所开发的要好的多。3、整个应用软件的复用,像Web开发中经常使用的数据库软件,软件的复用一般情况下对安全可控性会产生担忧。

       从上述可以得出使用依赖注入技术(不管是基于那种依赖注入容器),那么就已经默认遵循了控制反转的开发思想。MVC把一个类型的控制器定义标准是“类型名称”+“Controller”,即如果你看到一个后缀为“Controller” 的类,那么你就可以得出它是MVC中一个类型的控制器。同理只要使用依赖注入容器就是控制反转思想和依赖注入技术的标准,虽然不同的容器在实际开发中,会有一些定义和配置上有一些不相同,但它们都遵循一个最基本的标准:

类型对象的初始化操作只依赖于接口的声明

       对于初学者来说,不必关心和理解谁控制了谁,谁依赖于谁只要记住两点:

1、“控制转”是指类型对象的初始化操作是由依赖注入容器结合构造函数注入类型对象接口或属性注入类型对象接口所控制的,而不是由new关键字结合类型对象实例的显式所控制的。

2、依赖注入即是类型对象初始化操作的过程,在整个过程中是隐式的通过构造函数注入类型对象接口或属性注入类型对象接口实现的,而不是由new关键字结合类型对象实例的显式实现的。

       .NetCore框架是通过默认依赖注入容器结合“构造函数注入(constructor injection)”(这种注入方式遵循了显式依赖原则 (Explicit Dependencies Principle),而MEF依赖注入容器结合“属性”注入方式遵循了隐式依赖原则),实现依赖注入操作的。

//IServiceCollection:using Microsoft.Extensions.DependencyInjection;

            //(内置DI组件)依赖注入服务集合实例。

            IServiceCollection services = new ServiceCollection();

            //UseSqlServer:NuGet----Microsoft.EntityFrameworkCore.SqlServer----using Microsoft.EntityFrameworkCore;

            services.AddDbContext<CoreContext>(options => options.UseSqlServer(JsonOption.GetConnectionString()));

            services.AddScoped<IUnitOfWork, UnitOfWork>();

            ServiceProvider _provider = services.BuildServiceProvider();

            IUnitOfWork _unitOfWork = _provider.GetService<IUnitOfWork>();

       IServiceCollection接口所实例化的是默认依赖注入服务集合(也可以叫做默认依赖注入服务池),它的实例用于存储一个或多个类型对象实现与其接口声明的关联映射实例。AddDbContext方法是专门用于实例并初始化继承于DbContext类的对象(这里是CoreContext),如果没有这个继承则这行语句可以不写。如果程序需要实例化继承于DbContext类的对象,则必须使用AddScoped方法,它不支持AddSingleton、AddTransient方法。ServiceProvider实例在.NetCore默认依赖注入中不仅是一个解析器,而且是一个容器,是一个依赖注入的容器,它通过对特定类型对象的接口从依赖注入服务集合获取并初始化特定类型对象的实例。到此通过上述代码可以很直观的看到类型对象的初始化是通过依赖注入容器实现的,而不是通过new关键字。

在.NetCore框架提供的默认依赖注入的技术实现中,还有三个伴随出现的用于生命周期控制的方法:AddSingleton、AddScoped、AddTransient。在基于MVC架构的Web开发中方法:

  public IActionResult Index()

        {

            _tal += 1;

            ViewBag.MessageIndex = string.Format("执行第{0}次操作。", _tal);

            ViewBag.MessageIndexGroup = string.Format("执行第{0}次操作。", _talGroup);

            return View();

        }

        [HttpPost]

        public IActionResult Index(long group)

        {

            int _number = 10000;

            for (int i = 1; i <= _number; i++)

            {

                _unitOfWorkMock.Add(i);

            }

 

            _talGroup += 1;

            ViewBag.MessageIndex = string.Format("执行第{0}次操作。", _tal);

            ViewBag.MessageIndexGroup = string.Format("执行第{0}次操作。", _talGroup);

            //return Index();

            return View();

        }

如果两者都返回的是return View(),则两对应的是两个不同的进程,如果在类型显式的定义

#region 销毁--覆盖

        /// <summary>

        /// 【销毁】

        /// </summary>

        /// <remarks>

        ///    在向数据库提交数据时即 [HttpPost]方法时,UnitOfWorkService.Dispose()会被执行两次,

        ///第1次是向数据库提交数据时UnitOfWorkService.Dispose()会被执行,第2次是执行跳转页方法时会被执行。

        /// </remarks>

        /// <returns>无返回</returns>

        protected override void Dispose(bool isDisposing)

        {

            _unitOfWork.Dispose();

            base.Dispose(isDisposing);

        }

        #endregion

方法,Index()和Index(long group)方法在执行完成后都会调用Dispose(bool isDisposing)方法对自身进程所对应的内存进行销毁释放操作。对Index()和Index(long group)方法进行重复操作,每一次操作都对应一个新的进程,所以同样Index()和Index(long group)方法在执行完成后也都会调用Dispose(bool isDisposing)方法对自身进程所对应的内存进行销毁释放操作。

如果在Index(long group)方法中返回return Index(),在Index()返回Index(long group)那么两个方法两个方法将被拼接进一个进中在执行重复操作时只有个方法完成条件后调用并返回return View()这个进程才算结束并调用Dispose(bool isDisposing)方法对自身进程所对应的内存进行销毁释放操作。

       通过执行“2019-12-22_DICore(005WEB动态实例UnitOfWork,内存监视生命周期)”和” 2019-12-23_DICore(006WEB动态实例UnitOfWork-Dispose,内存监视生命周期)”,如果使用AddSingleton生命周期控制方法,从程序开始执行,到程序执行结束,不管同样的操作被重复执行多少次,都是对同一个进程中的同一个类型对象的实例进行操作,如果不调用Dispose(bool isDisposing)方法对象的实例在重复执行过程中所占的内存会根据调用的次数和量级呈线性的增加;如果调用Dispose(bool isDisposing)方法,对象的实例会在程序的执行的开始先销毁并释放掉UnitOfWork构造方法中的对象的实例,其后每次的都是同一个进程中的同一个类型对象实例的内存存储和销毁并释放的操作。AddScoped生命周期控制方法只能控制一个请求或提交中的类型对象实例的内存存储和销毁并释放的操作,在使用AddScoped时虽然类型对象的实例是相同的,但是进程是不同的,在重复执行请求或提交操作的过程是同一个类型对象实例,执行了不同的进程和线程,如果使用Dispose(bool isDisposing)方法方法它也只会对当前的请求或提交操作所产生的内存进行销毁并释放操作,不会影响UnitOfWork构造方法中的由种子数据所初始化的对象的实例。这是一种发布--订阅模式,首先订阅者对发布者无何的影响,同时订阅者之间无何的影响,他们只与发布者的初始化种子数据和他们所调用并执行的操作相关,这也是继承于DbContext类的对象,则必须使用AddScoped方法,它不支持AddSingleton、AddTransient方法原因所在。AddTransient生命周期控制方法操作流程和原理在执行return View()之前与AddSingleton相同,订阅者调用或执行的操作所产生的数据在执行return View()之后的同时类型对象实例由请求或提交操作所产生的数据就立即被销毁并释放,所以订阅者不会得到自己的操作数据,只会得到发布者的种子数据。

 2019-12-20_DICore(001控制台动态实例UnitOfWork调用模式,完成Insert、Update、Delete数据操作验证)  -- https://download.csdn.net/download/zhoujian_911/12047755。

2019-12-20_DICore(002控制台动态实例UnitOfWork调用模式,MiniProfiler10组1000次读写性能监视)  --https://download.csdn.net/download/zhoujian_911/12047756。

2019-12-20_DICore(003WEB动态实例UnitOfWork调用模式,MiniProfiler读写性能监视)   --https://download.csdn.net/download/zhoujian_911/12047757。

 2019-12-22_DICore(004WEB动态实例UnitOfWork-Dispose调用模式,10组10000次读写) -- https://download.csdn.net/download/zhoujian_911/12047760。

2019-12-22_DICore(005WEB动态实例UnitOfWork,内存监视生命周期).rar  --https://download.csdn.net/download/zhoujian_911/12047762。

2019-12-23_DICore(006WEB动态实例UnitOfWork-Dispose,内存监视生命周期).rar   --https://download.csdn.net/download/zhoujian_911/12047764。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值