在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里做依赖注入的更多相关文章

  1. [ASP.NET Core开发实战]基础篇02 依赖注入

    ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...

  2. ASP.NET Core 在 JSON 文件中配置依赖注入

    前言 在上一篇文章中写了如何在MVC中配置全局路由前缀,今天给大家介绍一下如何在在 json 文件中配置依赖注入. 在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等 ...

  3. Asp.Net Core 进阶(三)—— IServiceCollection依赖注入容器和使用Autofac替换它

    Asp.Net Core 提供了默认的依赖注入容器 IServiceCollection,它是一个轻量级的依赖注入容器,所以功能不多,只是提供了基础的一些功能,要实现AOP就有点麻烦,因此在实际工作当 ...

  4. .NET Core ASP.NET Core Basic 1-2 控制反转与依赖注入

    .NET Core ASP.NET Core Basic 1-2 本节内容为控制反转与依赖注入 简介 控制反转IOC 这个内容事实上在我们的C#高级篇就已经有所讲解,控制反转是一种设计模式,你可以这样 ...

  5. 转载:ASP.NET Core 在 JSON 文件中配置依赖注入

    在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等)时候,都是提供了专有的接口以供使用第三方的依赖注入组件,比如我们常用的会使用 Autofac.Untiy.Stri ...

  6. ASP.NET Core 2.2 基础知识(一) 依赖注入

    依赖: 类A用到了类B,我们就说类A依赖类B.如果一个类没有任何地方使用到,那这个类基本上可以删掉了. public class Test { private MyDependency md = ne ...

  7. ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用

    前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...

  8. asp.net core mvc 在中间件中使用依赖注入问题:System.InvalidOperationException: Cannot resolve scoped service 'IXXXService' from root provider.

    今天在弄JWT的时候需要用到用户验证使用一个自己写好的验证,但在出现了:System.InvalidOperationException: Cannot resolve scoped service ...

  9. .net core程序中使用微软的依赖注入框架

    我之前在博文中介绍过Asp.net core下系统自带的依赖注入框架,这个依赖框架在Microsoft.Extensions.DependencyInjection中实现,本身并不是.net core ...

随机推荐

  1. Vue-员工管理系统

    大二暑假进行了两周Vue的入门学习,主要内容就是关于前端的入门学习,在两周内学习了Vue的一些简单使用 主要就是使用数据的双向绑定,使用Vue进行数据处理,使用Bootstrap进行布局搭建,下面是我 ...

  2. Sqlserver表值函数来获取逗号分隔的ID

    其功能为: 将字符串如'1,2,3,4,5,6' 拼接成SQL里面的id 1:使用: select * from Student where id IN( SELECT * FROM dbo.F_SP ...

  3. 2019-09-17 thinkphp网页静态化

    public function details(){ $pid = I('get.goods_id'); $filename = "details_".$pid.".ht ...

  4. 用react-service做状态管理,适用于react、react native

    转载自:https://blog.csdn.net/wo_shi_ma_nong/article/details/100713151 . react-service是一个非常简单的用来在react.r ...

  5. logger.info占位符的使用

    {}表示占位符,使用方法如下: package org.pine.controller; import javax.annotation.Resource; import org.pine.servi ...

  6. 实验吧——你真的会PHP吗?(intval范围 php中\00的利用)

    题目地址:http://ctf5.shiyanbar.com/web/PHP/index.php 抓包在header中发现提示 访问得到源码 <?php $info = "" ...

  7. Kubernetes概念之deployment

    一整天一整天的坐在办公室,真的很~~~,懵圈中....,求解救. 本文通过<Kubernetes权威指南>的概念部分学习总结 Deployment作用 Deployment与RC的作用其实 ...

  8. 设计模式:单例(Sigleton)模式

    题目:设计一个类,我们只能生成该类的一个实例. 只能生成一个实例的类是实现了Singleton(单例)模式的类型. 相关知识: 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象 ...

  9. Django extend(继承)模板标签

    在 views.py 上修改 ... def ordered(req): return render(req, "ordered.html") def shopping_car(r ...

  10. Odoo form视图详解

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826350.html 一:Header头部 header区域一般用于展示文档流转的阶段和生命周期,以及动作 ...