.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应用程序中使用依赖注入的经验和建议. ...
随机推荐
- java使用jackson生成和解析JSON
java使用jackson生成和解析JSON 1.导包 2.生成json和解析json package test; import com.fasterxml.jackson.core.JsonProc ...
- “淘宝技术这十年”
"少时淘气,大时淘宝" 时势造英雄 起因eBay 易趣 在资本方面对仗,阿里想趁此崛起新项目就要求能在短时间内做出一个 个人对个人的商品交易网站(C2C)2003年4月7日-5月1 ...
- 来自澳洲的数据秀场:记KDD 2015大会
作者:微软亚洲研究院实习生 王英子 南半球最大城市和数据挖掘界顶级会议的浪漫碰撞 悉尼,作为澳大利亚第一大城市及新南威尔士州首府,澳大利亚的经济.金融.航运和旅游中心,同时还是南半球最大的城市和重要的 ...
- ndk-stack使用方法(转)
最近在mac上编译android 版本,各种崩溃让人蛋疼,网上学习了下ndk-stack使用方法. 自己备忘下: 1.运行终端. 跳转到你android sdk 目录 因为你的adb 在里面. 如 c ...
- Swift 进阶 第 4 课 集合类型协议
• Read 序列 一个序列 (sequence) 代表的是一系列具有相同类型 的值,你可以对这些值进行迭代.遍历一个序列最简单的方式是使用 for 循环: 123 for element in so ...
- Spark中Task数量的分析
本文主要说一下Spark中Task相关概念.RDD计算时Task的数量.Spark Streaming计算时Task的数量. Task作为Spark作业执行的最小单位,Task的数量及运行快慢间接决定 ...
- in和exists比较
in是把外表和内表作hash 连接,而exists 是对外表作loop 循环,每次loop 循环再对内表进行查询. 一直以来认为exists 比in 效率高的说法是不准确的.如果查询的两个表大小相当, ...
- js面试-手写代码实现new操作符的功能
我们要搞清楚new操作符到底做了一些什么事情? 1.创建一个新的对象 2.将构造函数的作用域赋给新对象(因此this指向了这个新对象) 3.执行构造函数中的代码(为这个新对象添加属性) 4.返回新对象 ...
- 7-30 jmu-python-凯撒密码加密算法 (10 分)
编写一个凯撒密码加密程序,接收用户输入的文本和密钥k,对明文中的字母a-z和字母A-Z替换为其后第k个字母. 输入格式: 接收两行输入,第一行为待加密的明文,第二行为密钥k. 输出格式: 输出加密后的 ...
- 05 mapreduce快速入门
统计HDFS的/wordcount/input/a.txt文件中的每个单词出现的次数——wordcount package cn.oracle.core; import java.io.IOExcep ...