Asp.net Core依赖注入(Autofac替换IOC容器)
ASP.NET Core
ASP.NET Core (previously ASP.NET 5) 改变了以前依赖注入框架集成进ASP.NET的方法. 以前, 每个功能 - MVC, Web API, 等. - 都有它自己的 "依赖解析器(dependency resolver)" 机制并且只是'钩子'钩住的方式有些轻微的区别. ASP.NET Core 通过 Microsoft.Extensions.DependencyInjection 引入了 conforming container 机制, 包含了请求生命周期作用域, 服务注册等等的统一概念.
在 ASP.NET Core 3.0, 引入了 "generic app hosting" 机制, 它可以应用在非 ASP.NET Core 应用中.
Autofac
中文官网:https://autofaccn.readthedocs.io/
入门
- Nuget引入 Autofac.Extensions.DependencyInjection 包.
- 在你的 Program.Main 方法内, 将Autofac附加给托管机制.(见下例)
- 在 Startup 类的 ConfigureServices 方法中用其他库提供的扩展方法注册东西到 IServiceCollection .
- 在 Startup 类的 ConfigureContainer 方法中直接注册东西到Autofac ContainerBuilder.
- IServiceProvider 会自动替你创建, 因此你无需做任何事只要 注册东西 即可.
ASP.NET Core 3.0+generic hosting
ASP.NET Core 1.1 - 2.2 使用方法, 你可以调用 WebHostBuilder 的 services.AddAutofac()
在ASP.NET Core 3.0托管方式发生了变化 并且需要不同的集成方式. 你不能在从 ConfigureServices 中返回 IServiceProvider, 也不能再将你的service provider factory加入到service collection.
下面是ASP.NET Core 3+ 和 .NET Core 3+ generic hosting support的集成方式:
Program类
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup类
添加方法 ConfigureContainer
public void ConfigureContainer(ContainerBuilder builder)
{
// 在这里添加服务注册
builder.RegisterType<TopicService>();
}
配置方法命名约定
- Configure, ConfigureServices, 和 ConfigureContainer 方法都支持基于你应用中 IHostingEnvironment.EnvironmentName 参数的环境特定命名约定. 默认地, 名称为 Configure, ConfigureServices, 和 ConfigureContainer.
- 如果你想要环境特定设置, 你可以把环境名称放在 Configure 部分后面, 类似 ConfigureDevelopment, ConfigureDevelopmentServices, 和 ConfigureDevelopmentContainer. 如果方法并不以匹配的环境名称显示, 它会回到默认方法.
这意味着你不必使用 Autofac配置在生产环境和开发环境之间切换; 你可以在 Startup 中以编程形式设置.
public void ConfigureDevelopmentContainer(ContainerBuilder builder)
{
}
public void ConfigureProductionContainer(ContainerBuilder builder)
{
// Add things to the ContainerBuilder that are only for the
// production environment.
}
这是ASP.NET Core应用托管的一个功能,它并不是Autofac的行为. ASP.NET Core中的StartupLoader类 是在应用启动时定位调用方法的.
控制器作为服务
默认地, ASP.NET Core 会从容器中解析控制器参数,但不会从中解析控制器 . 这并不是个问题但它意味着:
- 控制器 的生命周期归框架管理, 而非请求生命周期.
- 控制器构造方法参数 归请求生命周期管理.
- 在控制器注册时做的特别的连结 (如属性注入) 将不会生效.
通过在用service collection注册MVC时指定 AddControllersAsServices() , 你可以改变这个行为. 这么做可以在service provider factory调用 builder.Populate(services) 时自动注册控制器类型到 IServiceCollection.
public void ConfigureServices(IServiceCollection services)
{
//services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
//或者将Controller加入到Services中,这样写上面的代码就可以省略了
services.AddControllersWithViews().AddControllersAsServices();
}
如果需要在Controller中使用属性注入,需要在ConfigureContainer中添加如下代码
//如果需要在Controller中使用属性注入,需要在ConfigureContainer中添加如下代码
var controllerBaseType = typeof(ControllerBase);
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
.PropertiesAutowired();
在Controller中使用
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
private readonly TopicService _service;
private readonly IServiceProvider _provider;
public TopicService Service { get; set; }
public TestController(TopicService service, IServiceProvider provider)
{
_service = service;
_provider = provider;
}
[HttpGet("{id}")]
public async Task<Result> GetTopics(int id)
{
// 构造函数注入
return await _service.LoadWithPosts(id);
}
[HttpGet("Get/{id}")]
public async Task<Result> GetTopics2(int id)
{
// 属性注入
return await Service.LoadWithPosts(id);
}
}
这样就控制器就可以使用服务了。
多租户支持
由于ASP.NET Core想要早早地生成请求生命周期作用域, 这会导致多租户支持无法达到开箱即用的效果. 有时用于识别租户身份的 IHttpContextAccessor , 也无法被及时地构建. Autofac.AspNetCore.Multitenant 包就是用于解决这个问题的.
为了启用多租户支持:
- 添加 Autofac.AspNetCore.Multitenant NuGet包引用.
- 在 Program.Main 中构建web host时调用 UseServiceProviderFactory 和 AutofacMultitenantServiceProviderFactory. 提供一个配置租户的回调.
- 在 Startup.ConfigureServices 和 Startup.ConfigureContainer 中注册进入 根容器(root container) 的东西(那些非租户特有的).
- 在回调中 (如
Startup.ConfigureMultitenantContainer
) 构建你的多租户容器.
下面是Autofac给的一个示例:
public class Program
{
public static async Task Main(string[] args)
{
var host = Host
.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
.ConfigureWebHostDefaults(webHostBuilder => webHostBuilder.UseStartup<Startup>())
.Build();
await host.RunAsync();
}
}
... Startup 类似这样:
public class Startup
{
// Omitting extra stuff so you can see the important part...
public void ConfigureServices(IServiceCollection services)
{
// This will all go in the ROOT CONTAINER and is NOT TENANT SPECIFIC.
services.AddMvc();
// This adds the required middleware to the ROOT CONTAINER and is required for multitenancy to work.
services.AddAutofacMultitenantRequestServices();
}
public void ConfigureContainer(ContainerBuilder builder)
{
// This will all go in the ROOT CONTAINER and is NOT TENANT SPECIFIC.
builder.RegisterType<Dependency>().As<IDependency>();
}
public static MultitenantContainer ConfigureMultitenantContainer(IContainer container)
{
// This is the MULTITENANT PART. Set up your tenant-specific stuff here.
var strategy = new MyTenantIdentificationStrategy();
var mtc = new MultitenantContainer(strategy, container);
mtc.ConfigureTenant("a", cb => cb.RegisterType<TenantDependency>().As<IDependency>());
return mtc;
}
}
Asp.net Core依赖注入(Autofac替换IOC容器)的更多相关文章
- # ASP.NET Core依赖注入解读&使用Autofac替代实现
标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Aut ...
- ASP.NET Core依赖注入解读&使用Autofac替代实现【转载】
ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Autofac实现和自定义实现扩展方法 3.1 安装Autof ...
- ASP.NET Core 依赖注入基本用法
ASP.NET Core 依赖注入 ASP.NET Core从框架层对依赖注入提供支持.也就是说,如果你不了解依赖注入,将很难适应 ASP.NET Core的开发模式.本文将介绍依赖注入的基本概念,并 ...
- .net core 依赖注入, autofac 简单使用
综述 ASP.NET Core 支持依赖注入, 也推荐使用依赖注入. 主要作用是用来降低代码之间的耦合度. 什么是控制反转? 控制反转(Inversion of Control,缩写为IoC),是面 ...
- ASP.NET Core依赖注入初识与思考
文章首发地址 一.前言 在上一篇中,我们讲述了什么是控制反转(IoC)以及通过哪些方式实现的.这其中,我们明白了,控制反转(IoC) 是一种软件设计的模式,指导我们设计出更优良,更具有松耦合的程序,而 ...
- [译]ASP.NET Core依赖注入深入讨论
原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...
- ASP.NET Core依赖注入最佳实践,提示&技巧
分享翻译一篇Abp框架作者(Halil İbrahim Kalkan)关于ASP.NET Core依赖注入的博文. 在本文中,我将分享我在ASP.NET Core应用程序中使用依赖注入的经验和建议. ...
- 实现BUG自动检测 - ASP.NET Core依赖注入
我个人比较懒,能自动做的事绝不手动做,最近在用ASP.NET Core写一个项目,过程中会积累一些方便的工具类或框架,分享出来欢迎大家点评. 如果以后有时间的话,我打算写一个系列的[实现BUG自动检测 ...
- asp.net core 依赖注入几种常见情况
先读一篇注入入门 全面理解 ASP.NET Core 依赖注入, 学习一下基本使用 然后学习一招, 不使用接口规范, 直接写功能类, 一般情况下可以用来做单例. 参考https://www.cnblo ...
- ASP.NET Core依赖注入——依赖注入最佳实践
在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...
随机推荐
- Chisel3 - Wire & Reg
https://mp.weixin.qq.com/s/Y26N5P4XOr5e3uyi5XQY-w 不同于Verilog,Chisel中Wire和Reg并不是数据类型,而是数据容器,作为数据的一个 ...
- Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
833. 字符串中的查找与替换 对于某些字符串 S,我们将执行一些替换操作,用新的字母组替换原有的字母组(不一定大小相同). 每个替换操作具有 3 个参数:起始索引 i,源字 x 和目标字 y.规则是 ...
- Java实现 LeetCode 116 填充每个节点的下一个右侧节点指针
116. 填充每个节点的下一个右侧节点指针 给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点.二叉树定义如下: struct Node { int val; Node *left ...
- Java实现 LeetCode 19删除链表的倒数第N个节点
19. 删除链表的倒数第N个节点 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当 ...
- java实现第四届蓝桥杯埃及分数
埃及分数 古埃及曾经创造出灿烂的人类文明,他们的分数表示却很令人不解.古埃及喜欢把一个分数分解为类似: 1/a + 1/b 的格式. 这里,a 和 b 必须是不同的两个整数,分子必须为 1 比如,2/ ...
- CVE¬-2020-¬0796 漏洞复现(本地提权)
CVE-2020-0796 漏洞复现(本地提权) 0X00漏洞简介 Microsoft Windows和Microsoft Windows Server都是美国微软(Microsoft)公司的产品 ...
- 记 Centos zabbix-agent启动失败解决思路
一. 环境介绍 系统版本:Centos7.4 zabbix-agent 版本:zabbix-agent 3.4.7 二. 问题现象 启动zabbix-agent时启动失败 查看zabbix-agent ...
- KVM NAT(网络地址转换模式)
NAT(网络地址转换模式) 使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网.也就是说,使用NAT模式可以实现在虚拟系统里访问互联网.很显然,如果你只有一 ...
- R调用python模块
明明已经安装了sctransfer,但仍然显示没有该模块 Error in py_module_import(module, convert = convert) : ModuleNotFoundEr ...
- js循环练习
var a=1; while(a>0){ var b=prompt('input number'); if(b>a){ alert('big'); } else if(b<a){ a ...