ASP.NET Core如何在ActionFilterAttribute里做依赖注入
在ASP.NET Core里,我们可以使用构造函数注入很方便地对Controller,ViewComponent等部件做依赖注入。但是如何给过滤器ActionFilterAttribute也用上构造函数注入呢?
问题
我的博客系统里有个用来删除订阅文件缓存的ActionFilter,想要在发生异常的时候记录日志。我的博客用的日志组件是NLog,因此不使用依赖注入的话,就直接使用LogManager.GetCurrentClassLogger()获得一个Logger的实例。整个过滤器的代码如下:
public class DeleteSubscriptionCache : ActionFilterAttribute
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public override void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(context);
DeleteSubscriptionFiles();
}
private void DeleteSubscriptionFiles()
{
try
{
// ...
}
catch (Exception e)
{
Logger.Error(e, "Error Delete Subscription Files");
}
}
}
然后在Action上去使用,和经典的ASP.NET MVC一样
[Authorize]
[HttpPost, ValidateAntiForgeryToken, DeleteSubscriptionCache]
[Route("manage/edit")]
public IActionResult Edit(PostEditModel model)
这当然可以没有问题的运行,但写代码最重要的就是逼格,这个代码耦合了NLog,而我的博客系统里其他地方早就在用ASP.NET Core的ILogger接口了。如果哪天日志组件不再用NLog了,那么这个地方的代码就得改,而使用ILogger接口的代码就不需要动。虽然这种情况是绝对不会发生的,但是写代码一定要有追求,尽可能过度设计,才能不被人鄙视,然后才能面试造航母,工作拧螺丝。因此我决定把日志组件用依赖注入的方式安排一下。
改造过滤器
方法和在Controller中使用依赖注入完全一样,我们使用构造函数注入ILogger<DeleteSubscriptionCache>类型。于是代码变成了这样:
public class DeleteSubscriptionCache : ActionFilterAttribute
{
protected readonly ILogger<DeleteSubscriptionCache> Logger;
public DeleteSubscriptionCache(ILogger<DeleteSubscriptionCache> logger)
{
Logger = logger;
}
public override void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(context);
DeleteSubscriptionFiles();
}
private void DeleteSubscriptionFiles()
{
try
{
// ...
}
catch (Exception e)
{
Logger.LogError(e, "Error Delete Subscription Files");
}
}
}
但是问题来了,这样的话我们是没法在Action上无脑使用了,因为构造函数要求传参。如果要自己new一个的话,装逼就失败了。我们来看看正确的解决方法~
ServiceFilter
其实ASP.NET Core里,我们可以使用ServiceFilter来完成这个需求。它也是一种Attribute,可以作用在Action上。位于Microsoft.AspNetCore.Mvc.Core程序集里,定义如下:
// A filter that finds another filter in an System.IServiceProvider.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class ServiceFilterAttribute : Attribute, IFilterFactory, IFilterMetadata, IOrderedFilter
{
public ServiceFilterAttribute(Type type);
public int Order { get; set; }
public Type ServiceType { get; }
public bool IsReusable { get; set; }
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider);
}
ServiceFilter允许我们解析一个已经添加到IoC容器里的服务,因此我们需要把DeleteSubscriptionCache注册一下:
services.AddScoped<DeleteSubscriptionCache>();
然后就能直接使用了:
[Authorize]
[HttpPost, ValidateAntiForgeryToken]
[ServiceFilter(typeof(DeleteSubscriptionCache))]
[Route("manage/edit")]
public IActionResult Edit(PostEditModel model)
运行时发现ILogger已经能被实例化了,完美!
参考资料:
https://stackoverflow.com/questions/36109052/inject-service-into-action-filter/36109690
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2
ASP.NET Core如何在ActionFilterAttribute里做依赖注入的更多相关文章
- [ASP.NET Core开发实战]基础篇02 依赖注入
ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...
- ASP.NET Core 在 JSON 文件中配置依赖注入
前言 在上一篇文章中写了如何在MVC中配置全局路由前缀,今天给大家介绍一下如何在在 json 文件中配置依赖注入. 在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等 ...
- Asp.Net Core 进阶(三)—— IServiceCollection依赖注入容器和使用Autofac替换它
Asp.Net Core 提供了默认的依赖注入容器 IServiceCollection,它是一个轻量级的依赖注入容器,所以功能不多,只是提供了基础的一些功能,要实现AOP就有点麻烦,因此在实际工作当 ...
- .NET Core ASP.NET Core Basic 1-2 控制反转与依赖注入
.NET Core ASP.NET Core Basic 1-2 本节内容为控制反转与依赖注入 简介 控制反转IOC 这个内容事实上在我们的C#高级篇就已经有所讲解,控制反转是一种设计模式,你可以这样 ...
- 转载:ASP.NET Core 在 JSON 文件中配置依赖注入
在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等)时候,都是提供了专有的接口以供使用第三方的依赖注入组件,比如我们常用的会使用 Autofac.Untiy.Stri ...
- ASP.NET Core 2.2 基础知识(一) 依赖注入
依赖: 类A用到了类B,我们就说类A依赖类B.如果一个类没有任何地方使用到,那这个类基本上可以删掉了. public class Test { private MyDependency md = ne ...
- ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用
前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...
- asp.net core mvc 在中间件中使用依赖注入问题:System.InvalidOperationException: Cannot resolve scoped service 'IXXXService' from root provider.
今天在弄JWT的时候需要用到用户验证使用一个自己写好的验证,但在出现了:System.InvalidOperationException: Cannot resolve scoped service ...
- .net core程序中使用微软的依赖注入框架
我之前在博文中介绍过Asp.net core下系统自带的依赖注入框架,这个依赖框架在Microsoft.Extensions.DependencyInjection中实现,本身并不是.net core ...
随机推荐
- Linux系统SSH免密登录
第一章 生成密钥 1.1 生成用户默认文件名的密钥 [root@localhost ~] ssh-keygen -t rsa # root用户下生成root用户的默认密钥 1.2 生成用户指定文件名的 ...
- 关于在linux上部署scrapy的爬虫
1.在服务器中安装chrome sudo apt-get install libxss1 libappindicator1 libindicator7 wget https://dl.google.c ...
- Java I/O系统学习系列二:输入和输出
编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象.“流”屏蔽了实际的I/O设备中处理数据的细节. 在这个系列的第一篇文章:<< ...
- 遇到了Microsoft Visual Studio is Busy!
最近两天,我点击F5进入调试模式,VS左下角状态显示一直在加载符号文件,然后加载的超级慢,不多一会儿,显示VS正忙!如上图所示. 然后的然后,VS就卡死了~~~.之后,在网上查找原因和解决办法,找来找 ...
- Java操作ElasticSearch之创建客户端连接
Java操作ElasticSearch之创建客户端连接 3 发布时间:『 2017-09-11 17:02』 博客类别:elasticsearch 阅读(3157) Java操作ElasticSe ...
- Ubuntu拒绝root用户ssh远程登录
sudo vim /etc/ssh/sshd_config 找到并用#注释掉这行:PermitRootLogin prohibit-password 新建一行 添加:PermitRootLogin y ...
- 海思3519 qt ffmpeg 软解码播放avi
在海思3519上基于qt采用ffmpeg对avi进行解码显示,其中ffmpeg的配置,qt的配置在前文中已经说明,在此不再赘述. 解码 解码在单独的线程中进行,具体的代码如下: void VideoP ...
- MySQL事务优化
====================事务特性 事务隔离级别 事务控制语句 MySQL优化==================== 事务的概念 事务指逻辑上的一组操作,组成这组操作的各个单元,要么全 ...
- 浅谈僵尸网络利器:Fast-flux技术
浅谈僵尸网络利器:Fast-flux技术 一.背景 在早期的僵尸网络中,控制者通常会把C&C服务器的域名或者IP地址硬编码到恶意程序中,僵尸主机通过这些信息定时访问C&C主机获取命 ...
- Fluter基础巩固之Dart语言详解<二>
继续学习枯燥的Dart语言语法,目前的耐得住寂寞是为了将来学得“爽”做准备的!!! 异常: Dart 提供了 Exception 和 Error 类型, 以及一些子类型.还可以定义自己的异常类型.但是 ...