论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
应用中心
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
qidao123.com技术社区-IT企服评测·应用市场
»
论坛
›
大数据
›
数据仓库与分析
›
ASP.NET Core依赖注入之旅:针对服务注册的验证 ...
ASP.NET Core依赖注入之旅:针对服务注册的验证
干翻全岛蛙蛙
论坛元老
|
2022-9-16 17:15:01
|
显示全部楼层
|
阅读模式
楼主
主题
1733
|
帖子
1733
|
积分
5199
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
1.避免Scoped模式注册的服务变成Singleton模式
当提供一个生命周期模式为Singleton的服务实例时,如果发现该服务中还依赖生命周期模式为Scoped的服务实例(Scoped服务实例将被一个Singleton服务实例所引用),那么这个
被依赖的Scoped服务实例最终会成为一个Singleton模式的服务实例。
这是因为提供Singleton服务的容器是根容器,Scoped服务间接的被根容器所创建提供了,如果Scoped服务由子容器进行提供,那么Singleton和Scoped这两种生命周期模式才会产生差别。
在ASP.NET Core应用中,将某个服务注册的生命周期设置为Scoped,其意图是希望Scoped服务实例的创建和释放是作用于某个HTTP请求范围内的。如果不注意,将Scoped服务实例引用到了Singleton服务实例中,对于这种情况Scoped和Singleton的服务实例没有区别的。这样的Scoped服务实例直到应用关闭才会被释放,这无疑违背我们使用Scoped模式的初衷。
这种“混淆”如果没有察觉到,可能会在实际的应用中造成难以估量的后果
,例如在Singleton服务中引用的Scoped服务是一个数据库连接对象,这会导致数据库长时间连接没有及时释放,从而导致程序出现异常。
为了避免Scoped模式注册的服务“隐式”的变成Singleton模式的服务带来的风险,
.NET Core为我们提供了一种验证方式来规避这样的行为,这个方式就是将ServiceProviderOptions配置对象的ValidateScopes属性设置为True。
当开启了这个验证后,依赖注入框架则会对注册Scoped模式的服务进行检查,
确保不会出现如下情况:
有根容器去提供Scoped的服务实例;
Singleton服务中存在对Scoped服务的依赖;
一旦开启针对Scoped模式服务的注册验证,如果存在以上的两种情况,那么程序启动时会抛出异常。
ValidateScopes的值在开发环境下默认值是为True,为了确保在生产环境或其他环境始终开启验证,我们可以在Program类的CreateHostBuilder方法中配置ServiceProviderOptions对象。
该验证方式被官方称作为“服务范围”的验证,并建议应用程序开启此验证,以确保我们注册Scoped模式的服务仅作用于某个服务范围,而不会“悄悄地”演变成作用于整个应用程序范围的Singleton模式。
2.验证服务注册是否能够提供相应的实例
依赖注入框架中进行服务注册的信息一般都存放于ServiceDescriptor的对象中,而容器对象就是根据ServiceDescriptor对象中的注册信息进行服务实例的提供。ServiceProviderOptions配置类型除了用于针对“服务范围”的验证ValidateScopes属性之外,还有一个
ValidateOnBuild
属性。如果将该属性设置为True,这就意味着容器对象在构建时,会对每个ServiceDescriptor对象中的注册信息实施有效性验证,如果服务注册信息不能提供出对应的实例则会抛出异常。
使用ValidateOnBuild属性进行验证的目的是因为,往往有些服务能够正常注册但不代表,容器能够根据注册信息成功的提供实例。下面我将通过一个代码示例来印证这一情况,并演示使用ValidateOnBuild属性进行验证的方式。
1 using Microsoft.Extensions.DependencyInjection;
2 using System;
3 using System.Diagnostics;
4
5 namespace ConsoleApp1
6 {
7
8 public interface IFooBar { }
9 public class FooBar : IFooBar
10 {
11 private FooBar() { }
12 }
13
14 internal class Program
15 {
16 static void Main(string[] args)
17 {
18 Console.WriteLine("ValidateOnBuild的值为True:");
19 BuildServiceProvider(true);
20 Console.WriteLine();
21
22 Console.WriteLine("ValidateOnBuild的值为False:");
23 BuildServiceProvider(false);
24
25 } // END Main()
26
27 static void BuildServiceProvider(bool validateOnBuild)
28 {
29 try
30 {
31 var options = new ServiceProviderOptions { ValidateOnBuild = validateOnBuild };
32 var provider= new ServiceCollection()
33 .AddSingleton<IFooBar, FooBar>()
34 .BuildServiceProvider(options);
35 Console.WriteLine($"程序运行正常;");
36 }
37 catch (Exception e)
38 {
39 Console.WriteLine($"程序出现异常;异常信息:{e.Message};");
40 }
41
42 } // END BuildServiceProvider()
43
44
45 }
46 }
复制代码
在上面的代码示例中,服务注册时指定的实现类型为FooBar,而该类型中唯一的构造函数是一个私有的。我们都知道创建对象的实例,则必须要调用对象类型的构造函数,而FooBar的构造函数是私有的,无法对外界所调用,则也意味着无法创建相应的实例。
运行上面的代码示例后我们会发现,对于ValidateOnBuild属性值设置为False的情况,程序可以正常的执行服务注册的方法,这种现象隐瞒了注册时的错误(类型中存在私有构造函数),这种做法显然会对后续使用到FooBar对象的程序功能带来影响。
而对于ValidateOnBuild属性值设置为True的情况,程序则直接抛出了异常并且给出了详细的错误信息,对于这种做法我们可以更好的规避服务注册时所产生的风险。
本示例代码是在“服务定位器模式”下配置的ValidateOnBuild属性,这是为了更好的演示。当然,我们在实际的开发中通常是依赖注入的形式,那么相应的方式是通过在CreateHostBuilder方法中ServiceProviderOptions对象进行配置,如下图:
3.总结
本文介绍的关于“针对服务注册的验证”的主题,实际上就是介绍ServiceProviderOptions类型中
ValidateScopes
和
ValidateOnBuild
属性的使用场景和方式。VailedateScopes属性主要确保我们注册的Scoped服务不会在某些情况下变成Singleton服务,ValidateOnBuild属性主要用于验证服务注册信息是否能成功的提供出对应的服务示例。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
干翻全岛蛙蛙
论坛元老
这个人很懒什么都没写!
楼主热帖
Mac 上下载安装《鸣潮》详细教程(含更 ...
SQL的函数
Android Studio实现一个校园图书管理系 ...
ES6案例 ------ 模拟浏览器网页顶部切 ...
我为什么选择Wiki.js记笔记? ...
批量下载浏览器网页中全部链接的方法 ...
类与对象的创建
什么是超融合?
sql注入详解
5种kafka消费端性能优化方法
标签云
渠道
国产数据库
集成商
AI
运维
CIO
存储
服务器
快速回复
返回顶部
返回列表