前言

本文主要是详解一下在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. PHP开发小技巧,让你瞬间提升逼格

    说到PHP代码的优化,PHP开发的小技巧我想很多人都有自己的一套,下面分享一些小技巧,希望对大家有所帮助. 1.循环内部不要声明变量,尤其是对象这样的变量. 2.foreach效率更高,尽量用fore ...

  2. Python:list 和 array的对比以及转换时的注意事项

    Python:list 和 array的对比以及转换时的注意事项 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-6-4 ...

  3. linux下脚本做成服务

    一.脚本做成服务 1.把启动脚本复制到 /etc/init.d目录中 2.脚本内容 xxxx代表jar包名称 #!/usr/bin/env bash # chkconfig: 2345 20 80 # ...

  4. Linux文件系统概述

    Unix文件是以字节序列组成的信息载体(container),内核不解释文件的内容. Linux文件系统中的文件是数据的集合,文件系统不仅包含着文件中的数据而且还有系统的结构,所有Linux用户和程序 ...

  5. iOS APP跳转设置界面以及设置中的其他界面

    1.跳转设置总页面(iOS10+以及之前的都可以用:ios10+ 是跳转到了应用到设置界面) [[UIApplication sharedApplication]openURL:[NSURL URLW ...

  6. iOS知识点、面试题 之二

    最近面试,与大家分享一下,分三文给大家: 当然Xcode新版本区别,以及iOS新特性 Xcode8 和iOS 10 在之前文章有发过,感兴趣的可以查阅: http://www.cnblogs.com/ ...

  7. Jmeter+Ant+Jenkins接口自动化测试(二)_测试方案设计及jmeter脚本开发

    前言 根据之前部署好的测试环境,进行接口自动化测试的方案设计及Jmeter脚本开发.测试方案设计过程中采用了数据分离和对象分离等思路,因此直接通过特定的测试用例文档来驱动整个自动化接口测试的执行,相关 ...

  8. git push的用法

    git push <远程仓库名> <本地分支名>:<远程分支名>

  9. Errors are values

    原文地址 https://blog.golang.org/errors-are-values Go程序员之间(特别是这些刚接触Go语言的新人)一个常见的讨论点是如何处理错误.谈话经常变成为对如下代码序 ...

  10. [编织消息框架][JAVA核心技术]cglib动态代理

    先在mavne项目里添加cglib库 maven仓库搜索cglib版本 maven地址:http://mvnrepository.com/ 点击最新的版本 3.2.5 复制到pom.xml  depe ...