.net core 依赖注入, autofac 简单使用
综述
ASP.NET Core 支持依赖注入, 也推荐使用依赖注入. 主要作用是用来降低代码之间的耦合度.
什么是控制反转?
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。
其中最常见的方式叫做"依赖注入"(Dependency Injection,简称DI),还有一种方式叫"依赖查找"(Dependency Lookup)
什么是依赖注入?
这个概念分开来理解
1. 依赖, 当B类里要调用A类完成某个功能, 那么就可以说是B依赖于A.
public class ClassA
{
public string FnA(string str)
{
return "A-" + str;
}
} public class ClassB
{
ClassA ca = new ClassA();
public string FnB(string str)
{
var art = ca.FnA(str);
return "B-" + art;
}
}
上面这种方式是很常见的, 但是并不符合依赖的原则. 依赖的原则是: 依赖于抽象,而不是具体的实现. 也就是B类不能直接依赖A类, 应该依赖A的抽象接口.
2. 注入. 在这里C类不去实例化A类,而是通过其他人传递给我,我只用就好。简单来说就是别人对依赖创建实例化,我自己只负责使用,这个过程可以理解为注入.
public class ClassC
{
ClassA _ca;
public ClassC(ClassA ca)
{
_ca = ca;
}
public string FnC(string str)
{
var art = _ca.FnA(str);
return "C-" + art;
}
}
在上面的依赖中讲过, 最好不要直接依赖实现,应该依赖抽象接口. 通过注入我们了解到, 我们不应该直接实例化依赖项,而应该别人创建, 我们只负责使用. 综合一下, 我们就将原来的使用方式改为以下方式
/// <summary>
/// 抽象接口A
/// </summary>
public interface InterfaceA
{
string FnA(string str);
} /// <summary>
/// 抽象接口A的具体实现
/// </summary>
public class ClassA:InterfaceA
{
public string FnA(string str)
{
return "A-" + str;
}
} /// <summary>
/// 传统方式
/// </summary>
public class ClassB
{
ClassA ca = new ClassA();
public string FnB(string str)
{
var art = ca.FnA(str);
return "B-" + art;
}
}
/// <summary>
/// 依赖注入方式, 1.依赖于抽象接口,而不是具体实现; 2.依赖项不由我们自己创建,而只是负责使用
/// </summary>
public class ClassD
{
readonly InterfaceA _ica;
public ClassD(InterfaceA ica)
{
_ica = ica;
}
public string FnD(string str)
{
var art = _ica.FnA(str);
return "D-" + art;
}
}
ClassB就是我们常见的使用方式, ClassD就是我们使用依赖注入的使用方式.
如何在.net core 里使用依赖注入?
1. 创建抽象接口(过程略)
2. 实现抽象接口(过程略)
3. 在Startup类的ConfigureServices方法中注册服务
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<InterfaceA, ClassA>();
}
4. 在Controller中使用, 通过在构造函数中获取实例, 然后使用
[ApiController]
[Route("[controller]/[action]")]
public class DemoController : ControllerBase
{
private readonly InterfaceA _interfaceA;
/// <summary>
/// 通过构造函数获取实例
/// </summary>
/// <param name="interfaceA"></param>
public DemoController(InterfaceA interfaceA)
{
_interfaceA = interfaceA;
}
public IActionResult TestGet()
{
var rt = _interfaceA.FnA("uuu");
return Ok(rt);
}
}
结果
以上就是一个简单的.net core 使用依赖注入的例子
如何选择服务的生命周期?
在上面的第三步, 在注册服务的时候我们使用的AddTransient , 除此之外还有 AddScoped,AddSingleton
AddTransient 暂时
暂时生存期服务 (AddTransient) 是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。
AddScoped 范围内
作用域生存期服务 (AddScoped) 以每个客户端请求(连接)一次的方式创建。
注意:在中间件内使用有作用域的服务时,请将该服务注入至 Invoke 或 InvokeAsync 方法。 请不要通过构造函数注入进行注入,因为它会强制服务的行为与单一实例类似。 有关详细信息,请参阅 写入自定义 ASP.NET Core 中间件。
AddSingleton 单例
单一实例生存期服务 (AddSingleton) 是在第一次请求时(或者在运行 Startup.ConfigureServices 并且使用服务注册指定实例时)创建的。 每个后续请求都使用相同的实例。 如果应用需要单一实例行为,建议允许服务容器管理服务的生存期。 不要实现单一实例设计模式并提供用户代码来管理对象在类中的生存期。
注意:从单一实例解析有作用域的服务很危险。 当处理后续请求时,它可能会导致服务处于不正确的状态。
什么是容器?
讲到这里可能大家会有个疑问.
依赖注入把依赖的创建交给了别人, 我们只负责使用, 那么这个谁创建, 在哪儿创建, 怎么管理?
这个就引发了一个新的概念--容器. 容器就是负责管理系统所有的依赖. 在我们.net core 有一个默认的容器, 专门用于管理这些依赖.
但是默认的容器在小型项目的时候够了,但是大型项目就不够了.
我们通过AddTransient这些方式去注册服务, 那么一个项目有非常多的这种服务, 每一个都注册,在startup这个里面就变非常臃肿复杂. 这个时候我们需要替换原来的容器.
如何更换默认容器?
在这里我们介绍一种常用的第三方容器: AutoFac, .net core 版本使用的是3.1 其他版本会略有不同.
一. nuget安装 Autofac.Extensions.DependencyInjection
二. 修改 Program.cs 文件
添加一句
.UseServiceProviderFactory(new Autofac.Extensions.DependencyInjection.AutofacServiceProviderFactory())//Autofac
三. 修改 Startup.cs
新增ConfigureContainer方法
public void ConfigureContainer(ContainerBuilder builder)
{
// 方式一 默认注册
builder.RegisterType<ClassA>().As<InterfaceA>();//注册 类似默认容器的services.AddTransient<InterfaceA, ClassA>();
}
上面这种方式是默认的注册, 类似.net core 自带的注册. 但是并不合适我们批量注册, 下面介绍一种扫描程序集的注册方式
public void ConfigureContainer(ContainerBuilder builder)
{
//方式二 扫描程序集, RegisterAssemblyTypes接收包含一个或多个程序集的数组作为参数. 默认地, 程序中所有具体的类都将被注册.
var asm = Assembly.Load("Service");//指定dll名称的程序集集
var defulatAsm = Assembly.GetExecutingAssembly();//默认执行的dll
builder.RegisterAssemblyTypes(asm, defulatAsm)
.PublicOnly()//仅注册public的方法
.Except<Service.DemoService>()//排除某个类
.Where(t => t.Name.EndsWith("Service") || t.Name == "ClassA")//可以在这里写一些过滤类名规则
.AsImplementedInterfaces();
}
在controller里使用的方式和以前一样
参考文献
.net core 依赖注入, autofac 简单使用的更多相关文章
- # ASP.NET Core依赖注入解读&使用Autofac替代实现
标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Aut ...
- NET Core依赖注入解读&使用Autofac替代实现
NET Core依赖注入解读&使用Autofac替代实现 标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. ...
- 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 Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...
- .NET Core依赖注入集成Dynamic Proxy
在<Castle DynamicProxy基本用法>中介绍了如何将DP与Autofac集成使用,而 .NET Core有自己的依赖注入容器,在不依赖第三方容器的基础上,如何实现动态代理就成 ...
- net core 依赖注入问题
net core 依赖注入问题 最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久 ...
- ASP.NET Core依赖注入——依赖注入最佳实践
在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...
- ASP.NET Core 依赖注入最佳实践——提示与技巧
在这篇文章,我将分享一些在ASP.NET Core程序中使用依赖注入的个人经验和建议.这些原则背后的动机如下: 高效地设计服务和它们的依赖. 预防多线程问题. 预防内存泄漏. 预防潜在的BUG. 这篇 ...
- ASP.NET Core依赖注入最佳实践,提示&技巧
分享翻译一篇Abp框架作者(Halil İbrahim Kalkan)关于ASP.NET Core依赖注入的博文. 在本文中,我将分享我在ASP.NET Core应用程序中使用依赖注入的经验和建议. ...
随机推荐
- js javascript 获取url,获得当前页面的url,静态html文件js读取url参数
获得当前页面的url window.location.href 静态html文件js读取url参数 location.search; //获取url中"?"符后的字串 下边为转载的 ...
- form组件及cookie和session
多对多关系表的三种创建方式 1.全自动创建 优势:不需要你手动创建第三张表 不足:由于第三张表不是你手动创建的,也就意味着,第三张表字段是固定的无法更改 class Book(models.Model ...
- leetcode笔记——35.搜索插入位置 - CrowFea
0.问题描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 你可以假设数组中无重复元素. 示例 1: 12 输入: [1,3 ...
- CSS 双飞翼布局
10 Jul 2016 » CSS 双飞翼布局:总共分三栏,左侧栏Left,中间主栏Main,右侧栏Right 第一步,建立三个div,不过注意,中间Main需要加一个wrap div. 整个结构看起 ...
- ResultMap和ResultType到底有什么区别?
转载请标明出处:https://www.cnblogs.com/Dreamice/ 首先,SQL语句执行后返回的结果可以使用 Map 存储,也可以使用 POJO 存储. 一.使用Map存储结果集 下面 ...
- 探索Linux通用SCSI驱动器
通过 SCSI 命令管理计算机上的数据,并将数据传输到 SCSI 设备.在本文中,作者介绍了一些 SCSI 命令,以及在 Linux® 中使用 SCSI API 时执行 SCSI 命令的方法.他介绍了 ...
- redis BLPOP
一.需求 redis中保存了需要download的image url,存储格式为列表. 我需要从列表中获取数据,将图片下载保存到本地. 列表中的数据是一直增加的. 二.实现 使用redis BLPOP ...
- Channel Estimation for High Speed Wireless Systems using Gaussian Particle Filter and Auxiliary Particle Filter
目录 论文来源 摘要 基本概念 1.时变信道 2.粒子滤波 3.高斯粒子滤波 4.辅助粒子滤波 比较 借鉴之处 论文来源 International Conference on Communicati ...
- 基于Unix Socket的可靠Node.js HTTP代理实现(支持WebSocket协议)
实现代理服务,最常见的便是代理服务器代理相应的协议体请求源站,并将响应从源站转发给客户端.而在本文的场景中,代理服务及源服务采用相同技术栈(Node.js),源服务是由代理服务fork出的业务服务(如 ...
- 基于springcloud搭建项目-Ribbon篇(三)
这篇文章主要是介绍一下ribbon的用法,我们都知道ribbon是负载均衡,但是却不知道他是怎么样的负载均衡,怎么用,能干嘛? ● 其实,简单的说,Spring Cloud Ribbon是基于Netf ...