前言

本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期.

这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度.

目录

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

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

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

正文

上一篇我们说过ASP.NET Core中自带的IOC容器是属于轻量级的,功能并不是很多,只是提供了基础功能而已..

所以今天我们主要讲讲如何采用Autofac来替换IOC容器,并实现属性注入

注意:本文需要读者理解DI IOC并使用过相关框架.

1.将默认的IOC容器替换为Autofac

首先,我们需要从nuget引用相关的包.

Autofac

Autofac.Extensions.DependencyInjection(这个包扩展了一些微软提供服务的类.来方便替换autofac)

然后,我们修改Startup中的ConfigureServices代码如下:

        public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<BloggingContext>();
services.AddDirectoryBrowser();
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule<DefaultModule>();
containerBuilder.Populate(services);
var container = containerBuilder.Build();
return new AutofacServiceProvider(container);
}

这里我们使用了AutoFac的功能之一,模块化注入.也就是RegisterModule 这里, DefaultModule是我们的注入模块,代码很简单,如下:

    public class DefaultModule : Module
{
protected override void Load(ContainerBuilder builder)
{ //注入测试服务
builder.RegisterType<TestService>().As<ITestService>(); }
}

解释一下,在上面的代码中,我们配置IServiceProvider从Autofac容器中解析(设置一个有效的Autofac服务适配器)。

然后在整个框架中使用它来解析控制器的依赖关系,并在HttpContext上公开所有其他用例的服务定位。

这样我们就完成了初步的Autofac容器替换.下面我们创建控制器来看看效果.代码如下:

 public class AutoDIController : Controller
{ private readonly ITestService _testService; public AutoDIController(ITestService testService)
{
_testService = testService;
} // GET: AutoDI
public ActionResult Index()
{
ViewBag.date = _testService.GetList("Name");
return View();
}
}

当框架(通过一个命名为DefaultControllerActivator的服务)要创建一个控制器的实例时,它会解析IServiceProvider的所有构造函数依赖项.在上面的代码中,它会使用Autofac容器来解析产生类。

这样就能初步的达到我们替换IOC容器的的效果了..

但是,这个操作过程与asp.net MVC的不同之处在于.控制器本身不会从容器中解析出来,所以服务只能从它的构造器参数中解析出来。

所以.这个过程,让我们无法使用Autofac的一些更高级功能.比如属性注入(关于属性注入的好坏..属于仁者见仁智者见智的东西,这里我们不讨论它是好还是坏.)

2.如何使用Autofac的高级功能,属性注入.

我们回到Autofac设置代码,并设置属性注入如下:

 var containerBuilder = new ContainerBuilder();
//模块化注入
containerBuilder.RegisterModule<DefaultModule>();
//属性注入控制器
containerBuilder.RegisterType<AutoDIController>().PropertiesAutowired();
containerBuilder.Populate(services);

注入模块的代码修改如下:

//属性注入
builder.RegisterType<TestService>().As<ITestService>().PropertiesAutowired();

然后修改我们的控制器代码如下:

 public class AutoDIController : BaseController
{ public ITestService _testService { get; set; } // GET: AutoDI
public ActionResult Index()
{
ViewBag.date = _testService.GetList("Name");
return View();
}
}

这里我们剔除了控制器的构造函数.

我们运行代码,会发现_testService 为null,所以根本没有注入成功.失败的原因上面我们已经解释过了...但是还是强调一下吧..

虽然控制器的构造函数依赖性将由MVC从IServiceProvider解决(也就是我们之前构造函数注入的例子),

但是控制器本身的实例(以及它的处理)却是由框架创建和拥有的,而不是由容器所有。

那么我们该如何改变控制器本身的创建和所有者呢?

我们会在Microsoft.Extensions.DependencyInjection中找到一个方法.叫做AddControllersAsServices

它的注释翻译过来为:将控制器的寄宿器转为注册的服务(也就是我们替换的autofac).

但是,注意..这里虽然是将控制的所有者改成了autofac,但是我们还是不能使用相关的属性注入方法.

所以,我们到GITHUB上来看看这个方法源码如下.(这就是开源的好处...):

public static IMvcBuilder AddControllersAsServices(this IMvcBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
} var feature = new ControllerFeature();
builder.PartManager.PopulateFeature(feature); foreach (var controller in feature.Controllers.Select(c => c.AsType()))
{
builder.Services.TryAddTransient(controller, controller);
} builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); return builder;
}

我们会发现最后一句..

 builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

意思是用ServiceBasedControllerActivator替换DefaultControllerActivator(意味着框架现在会尝试从IServiceProvider中解析控制器实例)

..这下终于真相大白了..

我们只需要修改配置服务的代码如下:

     public IServiceProvider ConfigureServices(IServiceCollection services)
{
//替换控制器所有者
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
services.AddMvc();
services.AddDbContext<BloggingContext>();
services.AddDirectoryBrowser();
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule<DefaultModule>();
//采用属性注入控制器
containerBuilder.RegisterType<AutoDIController>().PropertiesAutowired();
// containerBuilder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired();
containerBuilder.Populate(services); var container = containerBuilder.Build();
return new AutofacServiceProvider(container);
}

注意,替换的方法一定要在addMVC之前..

然后我们运行我们的控制器代码.效果如图:

如图所示,_testService已经被实例化了.说明我们的属性注入就成功了~

写在最后

本篇到此就结束了,下篇我们讲解,如何使用Autofac的高级功能来实现我们的切面编程(AOP)

喜欢的请点个推荐和关注,~有问题也希望各位批评指正~.

ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)的更多相关文章

  1. gRPC在 ASP.NET Core 中应用学习(二)

    前言: 上一篇文章中简单的对gRPC进行了简单了解,并实现了gRPC在ASP.NET Core中服务实现.客户端调用:那么本篇继续对gRPC的4中服务方法定义.其他使用注意点进一步了解学习 一.gRP ...

  2. (9)ASP.NET Core 中的MVC路由二

    1.URL生成 MVC应用程序可以使用路由的URL生成功能,生成指向操作(Action)的URL链接. IUrlHelper 接口用于生成URL,是MVC与路由之间的基础部分.在控制器.视图和视图组件 ...

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

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

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

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

  5. ASP.NET Core:ASP.NET Core中使用NLog记录日志

    一.前言 在所有的应用程序中,日志功能是不可或缺的模块,我们可以根据日志信息进行调试.查看产生的错误信息,在ASP.NET Core中我们可以使用log4net或者NLog日志组件来实现记录日志的功能 ...

  6. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  7. 浅谈ASP.NET Core中IOC与DI的理解和使用

    说起IOC和DI,使用过ASP.NET Core的人对这两个概念一定不陌生,早前,自己也有尝试过去了解这两个东西,但是一直觉得有点很难去理解,总觉得对其还是模糊不清,所以,趁着今天有空,就去把两个概念 ...

  8. ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

    在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...

  9. (12)ASP.NET Core 中的配置二(Configuration)

    1.内存配置 MemoryConfigurationProvider使用内存中集合作为配置键值对.若要激活内存中集合配置,请在ConfigurationBuilder的实例上调用AddInMemory ...

随机推荐

  1. Shell编程之文本处理

    cut 截取自定列 可以按照某个字符进行分割,然后取出其中的指定列: [root@iz8vbbqbnh4ug2q9so5jflz logs]# --.txt /Dec/::: +] - /Dec/:: ...

  2. Natas Wargame Level27 Writeup(SQL表的注入/溢出与截取)

    前端: <html> <head> <!-- This stuff in the header has nothing to do with the level --&g ...

  3. spring boot部署系统--morphling简介

    Morphling 简介 Morphling是一套基于Spring Boot 1.5开发的部署系统,依赖简单,一套Mysql即可运行,操作简单明了,适用于百台规模几下机器的运维操作 功能概述 系统部署 ...

  4. 【二十一】基于mysqli的表格数据练习

    mysqlitest.php <?php //调用数据库的函数 function connetionsql(){ $conn=mysqli_connect("127.0.0.1&quo ...

  5. iOS 环信透传cmd消息多次重复接收,解决办法

    由于项目需求,需要在项目中接到消息的时候做不同界面的不同的操作,哪儿需要哪儿就要添加代理:引起代理事件重复执行:所以要在VC显示的时候添加代理,消失的时候删除代理 环信 透传 消息多次接收情况(由于代 ...

  6. SVO环境搭建

    我是装了双系统,实验OS:Ubuntu14.04 Installation: Plain CMake (No ROS) 首先,建立一个工作目录比如:workspace,然后把下面的需要的都在该目录下进 ...

  7. bzoj 1179: [Apio2009]Atm

    Description Input 第 一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路 的起点和终点的 ...

  8. lumen安装后输出hello world

    1.安装composer,具体请百度 2.composer 切换中国镜像,好处自己体会,命令如下 composer config -g repo.packagist composer https:// ...

  9. sql server 2012 新知识-序列

    今天聊一聊sql 2012 上的新功能-----序列 按我的理解,它就是为了实现全局性的唯一标识,按sql server 以前的版本,想对一张表标识很简单,比如identity,但如果要对某几张有业务 ...

  10. 点击按钮显示隐藏DIV,点击DIV外面隐藏DIV

    点击按钮显示隐藏DIV,点击DIV外面隐藏DIV 注意:此方法对touch事件不行,因为stopPropagation并不能阻止touchend的冒泡 <style type="tex ...