ASP.NET Core - 在ActionFilter中使用依赖注入

上次ActionFilter引发的一个EF异常,本质上是对Core版本的ActionFilter的知识掌握不够牢固造成的,所以花了点时间仔细阅读了微软的官方文档。发现除了IActionFilter、IAsyncActionFilter的问题,还有一个就是依赖注入在ActionFilter上的使用也是需要注意的地方。
当我们的ActionFilter需要使用某个Service的时候,我们一般会通过构造函数注入。
演示一下,首先自定义一个ActionFilter,通过构造函数注入IMyService:

    public interface IMyService{string GetServiceName(); }public class MyService : IMyService{public MyService (){Console.WriteLine("Service {0} created .", GetServiceName());}public string GetServiceName(){return "MyService";}}public class FilterInjectAttribute: ActionFilterAttribute{public FilterInjectAttribute(IMyService myService){if (myService == null){throw new ArgumentNullException("myService");}Console.WriteLine("Service {0} was injected .", myService.GetServiceName());}}

但是我们在使用Attribute的时候VS直接给出红色提示,需要传入构造函数的参数,否则无法编译过去。

当然我们可以直接new一个MyService来当做参数,但是很显然这样就失去了注入的那些好处了。

在ActionFilter中使用依赖注入

在ASP.NET Core的ActionFilter中使用依赖注入主要有两种方式:

  1. ServiceFilterAttribute

  2. TypeFilterAttribute

ServiceFilterAttribute

使用ServiceFilterAttribute可以使你的ActionFilter完成依赖注入。其实就是把你要用的ActionFilter本身注册为一个Service注册到DI容器中。通过ServiceFilter从容器中检索你的ActionFilter,并且注入到需要的地方。所以第一步就是要注册你的ActionFilter:

        public void ConfigureServices(IServiceCollection services){services.AddScoped<IMyService,MyService>();services.AddScoped(typeof(FilterInjectAttribute));services.AddControllers();services.AddRazorPages();}

然后新建一个Controller,在Action上使用ServiceFilter:

        [ServiceFilter(typeof(FilterInjectAttribute))]public string DI(){Console.WriteLine("HomeController method DI running .");return "DI";}

运行一下,在浏览器里访问下对应的path,可以看到MyService已经注入到FilterInjectAttribute中:

ServiceFilterAttribute的IsReusable属性:

ServiceFilter有一个属性叫IsReusable。从字面意思也很好理解,就是是否可重用的意思。显而易见如果这个属性设置为True,那么多个请求就会复用这个ActionFilter,这就有点像是单例的意思了。

        [ServiceFilter(typeof(FilterInjectAttribute), IsReusable = true)]public string DI(){Console.WriteLine("HomeController method DI running .");return "DI";}

运行一下,多次在浏览器中访问对应的action的path,可以看到FilterInjectAttribute的构造函数只会执行一次。

这里有一个重要提示, ASP.NET Core runtime 并不保证这个filter是真正的单例。所以不要试图使用这个属性来实现单例,并且业务系统依赖这个单例。

TypeFilterAttribute

使用TypeFilterAttribute也可以使你的ActionFilter完成依赖注入。它跟ServiceFilterAttribute差不多,但是使用TypeFilterAttribute注入的ActionFilter并不从DI容器中查找,而是直接通过Microsoft.Extensions.DependencyInjection.ObjectFactory来实例化对象。所以我们的FilterInjectAttribute不需要提前注册到DI容器中。首先注释掉FilterInjectAttribute的注册代码:

        public void ConfigureServices(IServiceCollection services){services.AddScoped<IMyService,MyService>();//services.AddScoped(typeof(FilterInjectAttribute));services.AddControllers();services.AddRazorPages();}

改用TypeFilterAttribute:

        [TypeFilter(typeof(FilterInjectAttribute))]public string DI(){Console.WriteLine("HomeController method DI running .");return "DI";}

运行一下,在浏览器里访问下对应的path,可以看到MyService已经注入到FilterInjectAttribute中:

TypeFilterAttribute的IsReusable属性:

跟上面的ServiceFilter一样,ASP.NET Core runtime 并不保证这个filter是真正的单例,这里就不多啰嗦了。

TypeFilterAttribute的Arguments属性:

Arguments参数是TypeFilterAttribute跟ServiceFilterAttribute的一个重要区别,ServiceFilterAttribute并没有这属性。Arguments类型为object数组。通过TypeFilterAttribute实例化的ActionFilter,如果它的构造器中的参数类型在DI容器中找不到,会继续在Arguments参数列表里按顺序获取。
改一下FilterInjectAttribute构造器多加入2个参数,并且保证这2个参数无法从DI中取到:

    public class FilterInjectAttribute: ActionFilterAttribute{public FilterInjectAttribute(string arg1, IMyService myService, string arg2){if (myService == null){throw new ArgumentNullException("myService");}Console.WriteLine("Service {0} was injected .", myService.GetServiceName());Console.WriteLine("arg1 is {0} .", arg1);Console.WriteLine("arg2 is {0} .", arg2);Console.WriteLine("FilterInjectAttribute was created .");}}

在使用的时候传入两个参数:

        [TypeFilter(typeof(FilterInjectAttribute), Arguments  = new object[] { "HAHA", "HOHO" })]public string DI(){Console.WriteLine("HomeController method DI running .");return "DI";}

运行一下看到两个参数被传入了FilterInjectAttribute的构造器:

总结

  1. ActionFilterAttribute的依赖注入可以通过ServiceFilterAttribute,TypeFilterAttribute来实现

  2. ServiceFilterAttribute是通过DI容器来管理ActionFilterAttribute;TypeFilterAttribute则是通过一个工厂直接实例化,所以使用前不需要注册到DI容器中。

  3. IsReusable属性可以实现类似单例的功能,但是运行时并不保证唯一单例。

  4. TypeFilterAttribute的Arguments属性可以作为参数列表。当实例化ActionFilterAttribute的时候如果构造器参数类型没有在DI容器中注册那么会尝试从Arguments列表中取。

关注我的公众号一起玩转技术

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304984.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

魏尔斯特拉斯函数与分形图形的动画演示

一般人会直觉上认为连续的函数必然是近乎可导的。即使不可导&#xff0c;所谓不可导的点也必然只占整体的一小部分。根据魏尔斯特拉斯在他的论文中所描述&#xff0c;早期的许多数学家&#xff0c;包括高斯&#xff0c;都曾经假定连续函数不可导的部分是有限或可数的。这可能是…

大脚战场插件怎么关闭_PM工具栏插件:HonmToolBar

视频演示&#xff1a;问&#xff1a;HonmToolBar是一款什么样的插件&#xff1f;答&#xff1a;HonmToolBar是一款高度自由化的插件&#xff0c;用户可以自己增加宏文件按钮或者宏命令按钮。该插件类似工具栏&#xff0c;有水平和垂直两个工具栏。插件悬浮在PM图形窗口左上角&a…

android 导航 美国,变美了 Android N或用全新虚拟导航按键

原标题&#xff1a;变美了 Android N或用全新虚拟导航按键变美了 Android N或用全新虚拟导航按键【IT168 资讯】虽然距离谷歌Android N系统的发布已经有一段时间了&#xff0c;不过该系统目前仍旧属于内测阶段&#xff0c;短时间内仍难以迅速推广。另外也正是由于Android N正式…

python特性和属性_Python面向对象-类的特性及公私有属性 | 【韩涛博客】

构造函数 __init__ self.name name #属性&#xff0c;成员变量&#xff0c;字段 def sayhi() #方法&#xff0c;动态属性 公有属性 在类中直接定义的属性&#xff0c;大家都可以用 私有属性 __两个下划线定义&#xff0c;外部不可以访问&#xff0c;内部可以访问 class Role(o…

[Abp 源码分析]自动审计记录

点击上方蓝字关注我们0.简介Abp 框架为我们自带了审计日志功能&#xff0c;审计日志可以方便地查看每次请求接口所耗的时间&#xff0c;能够帮助我们快速定位到某些性能有问题的接口。除此之外&#xff0c;审计日志信息还包含有每次调用接口时客户端请求的参数信息&#xff0c;…

我的老公是枚码农

前两天看到一篇写程序员的爆文&#xff0c;虽然略显夸张&#xff0c;但也着实有趣。忽然想到身边人也是一枚码农&#xff0c;浑身上下也是浓厚的码农气息&#xff0c;遂也胡乱写了几笔&#xff0c;博君一笑&#xff0c;为了方便起见&#xff0c;就称其为“码农哥”。 1 码农哥还…

harmonyos con,鸿蒙HarmonyOS系统中的JS开发框架

HarmonyOS开源至今已经一个多月&#xff0c;源码托管在国内知名开源平台码云上&#xff0c;https://gitee.com/openharmony 。我最感兴趣的就是JS 框架 ace_lite_jsfwk&#xff0c;从名字中可以看出来这是一个非常轻量级的框架&#xff0c;官方介绍说是“轻量级 JS 核心开发框架…

.NET工资低?那肯定是你打开的方式不正确

点击上方蓝字关注我们因为工作的关系&#xff0c;本人总是会接触到一些刚踏入社会没多久的.NET开发小伙伴。尤其是年关将近&#xff0c;这时候想要跳槽的人特别多&#xff0c;所以收到一些小伙伴的迷茫求解。今天就拿其中一个来说&#xff0c;我们暂且称他为A同学吧。A同学是一…

10分钟读懂人工智能、机器学习到底有什么关系

文末彩蛋&#xff0c;错过哭一年。。。。 人工智能的浪潮正在席卷全球&#xff0c;诸多词汇时刻萦绕在我们耳边&#xff1a;人工智能&#xff08;Artificial Intelligence&#xff09;、机器学习&#xff08;Machine Learning&#xff09;。不少人对这些高频词汇的含义及其背后…

苏泊尔搭载华为鸿蒙系统,华为鸿蒙打算在一年内跨过生死线,拿下16%的市场份额...

原标题&#xff1a;华为鸿蒙打算在一年内跨过生死线&#xff0c;拿下16%的市场份额华为鸿蒙操作系统发布已经有一段时间了&#xff0c;这个操作系统直到上个月月底才开启了公测&#xff0c;很多用户都已经使用上了华为的这个鸿蒙操作系统。根据不少用户的反馈情况来看&#xff…

python获取系统时间函数_简单记录python的时间函数操作

1. time和datetime模块 import datetime,time 2. 获得当前时间 time.time() #获得当前时间&#xff0c;返回float型 time.localtime([float time]) #获得本地当前时间&#xff0c;返回time.struct_time类型 说明&#xff1a;struct_time是一个只读的9元组&#xff0c;其中参数命…

10个最佳的大数据处理编程语言

大数据的浪潮仍在继续。它渗透到了几乎所有的行业&#xff0c;信息像洪水一样地席卷企业&#xff0c;使得软件越发庞然大物&#xff0c;比如Excel看上去就变得越来越笨拙。数据处理不再无足轻重&#xff0c;并且对精密分析和强大又实时处理的需要变得前所未有的巨大。 那么&…

再记一次 应用服务器 CPU 暴高事故分析

一&#xff1a;背景 1. 前言大概有2个月没写博客了&#xff0c;不是不想写哈????&#xff0c;关注公号的朋友应该知道我这两个月一直都在翻译文章&#xff0c;前前后后大概100篇左右吧&#xff0c;前几天看公号的 常读用户 降了好几十&#xff0c;心疼哈&#xff0c;还得回…

”残酷“人生第一步

仔仔终于要面对人生中的第一次巨大困难&#xff1a;断奶了。恰逢夫人要出差几日&#xff0c;刚刚开始&#xff0c;我们都很犹豫。确实很怕他整夜哭闹。但是思考再三还是决定&#xff0c;让小家伙独自面对吧。于是&#xff0c;他的“残酷”人生第一步&#xff0c;就这样准备开始…

IdentityServer4之Authorization Code(授权码)相对更安全

前言接着授权模式聊&#xff0c;这次说说Authorization Code(授权码)模式&#xff0c;熟悉的微博接入、微信接入、QQ接入都是这种方式(这里说的是oauth2.0的授权码模式)&#xff0c;从用户体验上来看&#xff0c;交互方式和Implicit没啥改变&#xff0c;随便找个网站瞅瞅&#…

后端根据百度地图真实路径距离_导航软件哪家强?实测百度地图and高德地图哪个更靠谱...

随着社会的不断发展&#xff0c;人们的生活越来越离不开地图导航&#xff0c;无论是开车出行还是到去到陌生的地方&#xff0c;我们都会用到手机地图。然而在众多导航软件中&#xff0c;使用最为广泛的就要属百度地图和高德地图了。但别看都是导航软件&#xff0c;其中差别还真…

一文读懂 KMP 算法

字符串匹配是计算机的基本任务之一。举例来说&#xff0c;有一个字符串"BBC ABCDAB ABCDABCDABDE"&#xff0c;我想知道&#xff0c;里面是否包含另一个字符串"ABCDABD"&#xff1f; 许多算法可以完成这个任务&#xff0c;Knuth-Morris-Pratt算法&#xff…

128位加密SSL证书

SGC超真SSL(SGC ZhenSSL)属于 SGC Enabled High Assurance SSL&#xff0c; 是 WoSign 的增强型 SSL证书产品&#xff0c;支持 SGC 强制128位加密技术&#xff0c;即使用户的浏览器只支持 40 位( 如 IE4.X) 或 56 位 ( 如 IE5.X) 也能自动强制实现至少 128 位的高强度加密&…

eclipse连接mysql_专题一、flask构建mysql数据库正确姿势

每周壹总结&#xff0c;一起共同充电第121篇应用程序最核心的就是数据&#xff0c;每天我们写程序其实也是在处理数据的过程&#xff0c;那么很有必要系统性的讲讲和梳理python的flask框架是如何进行数据交互操作的。趁这3天假期&#xff0c;分4篇内容来系统的讲讲&#xff0c;…

C#多线程和异步(二)——Task和async/await详解

一、什么是异步同步和异步主要用于修饰方法。当一个方法被调用时&#xff0c;调用者需要等待该方法执行完毕并返回才能继续执行&#xff0c;我们称这个方法是同步方法&#xff1b;当一个方法被调用时立即返回&#xff0c;并获取一个线程执行该方法内部的业务&#xff0c;调用者…