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 ...
随机推荐
- Blend 触发器
原文:Blend 触发器 介绍用定义触发器来控制视频 的 开始 暂停 继续 停止 触发器设置 效果
- (二)RFB协议具体通信说明
. 消息说明 8.1 握手消息 8.1.1 RFB协议版本号 1.vnc服务器发送所能够支持的最高RFB协议版本号给客户端,格式如下: “RFB xxx.yyy\n”共12b ...
- P3028 汽水机(差分)
题目 P3028 [USACO10OCT]汽水机Soda Machine 解析 差分,看到\(a[i]\leq 1e9\),离散化一下,在\(l\)处\(+1\),\(r+1\)处\(-1\),这样就 ...
- token安全之任意密码重置
前言 偶然间挖了一个漏洞是密码重置,挖掘过程很有趣,可以参考下. 挖掘过程 在说明之前我们可以先走下正常流程,这样才方便查漏~ 正常流程 第一步骤: 正常填写完,点击下一步发送请求: POST /[U ...
- android studio学习---Android studio 导入github工程
无论是那种方式,都最好是先把github上的工程项目下载到本地,然后修改文件再import 首先要知道 自己的build.gradle,在project下面的版本号是多少,比如我的: depende ...
- windows开启PostgreSQL数据库远程访问
1.在PostgreSQL安装目录下data文件夹,打开pg_hba.conf文件,新增允许访问的ip 2.打开postgresql.conf,将listen_addresses = 'localho ...
- 【IOS】libimobiledevice常用命令
libimobiledevice 是一个跨平台的软件库,支持 iPhone®, iPod Touch®, iPad® and Apple TV® 等设备的通讯协议. 安装 命令: brew ins ...
- Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition (ST-GCN)
Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition 摘要 动态人体骨架模型带有进行动 ...
- php状态模式(state pattern)
... <?php /* The state pattern encapsulates the varying behavior for the same object based on its ...
- django rest framework 认证组件
1.认证组件 1.认证组件 1.认证组件 1.认证组件