autofac使用拦截器实现AOP,是基于Castle.Core的.然而Castle.Core并未提供原生异步支持.所以需要使用帮助类实现,这在autofac官方文档的已知问题中有详细说明:

https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html#asynchronous-method-interception

对于该问题的讨论,最早出现于stackoverflow:https://stackoverflow.com/questions/28099669/intercept-async-method-that-returns-generic-task-via-dynamicproxy

James Skimming基于其中的一个答案,研发了一个帮助包即: Castle.Core.AsyncInterceptor

我之前也一直使用的是该方案,不过thepirat000随后提出了一个使用dynamic的更加简化的实现方法:https://stackoverflow.com/a/39784559/7726468

我对其进行了一些封装,实现了一个新的帮助包,大家可以尝试一下,项目地址在:https://github.com/wswind/lightwind

使用时,你可以通过nuget安装Lightwind.Asyncinterceptor也可以直接拷贝AsyncInterceptorBase.cs放入你的项目中.样例代码可点击这里查看

其中的核心代码是封装实现一个支持异步处理的Interceptor,让开发者仅需关心实现所拦截的方法,在执行前后该添加什么处理逻辑.

核心源码如下:

    //inspired by : https://stackoverflow.com/a/39784559/7726468
public abstract class AsyncInterceptorBase : IInterceptor
{
public AsyncInterceptorBase()
{
}
public void Intercept(IInvocation invocation)
{
BeforeProceed(invocation);
invocation.Proceed();
if (IsAsyncMethod(invocation.MethodInvocationTarget))
{
invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation);
}
else
{
AfterProceedSync(invocation);
}
} protected bool IsAsyncMethod(MethodInfo method)
{
var attr = method.GetCustomAttributes<AsyncStateMachineAttribute>(true);
bool isAsync = (attr != null) && typeof(Task).IsAssignableFrom(method.ReturnType);
return isAsync;
} private async Task InterceptAsync(Task task, IInvocation invocation)
{
await task.ConfigureAwait(false);
await AfterProceedAsync(invocation, false);
} protected object ProceedAsynResult { get; set; } private async Task<TResult> InterceptAsync<TResult>(Task<TResult> task, IInvocation invocation)
{
TResult result = await task.ConfigureAwait(false);
ProceedAsynResult = result;
await AfterProceedAsync(invocation,true);
return (TResult)ProceedAsynResult;
} protected virtual void BeforeProceed(IInvocation invocation) {} protected virtual void AfterProceedSync(IInvocation invocation) {} protected virtual Task AfterProceedAsync(IInvocation invocation,bool hasAsynResult)
{
return Task.CompletedTask;
}
}

异步拦截器的执行流程如下:

在所拦截的方法执行前,首先执行BeforeProceed,方法执行后,如果为同步方法,则后续执行AfterProceedSync

如果为异步方法,则await方法使其真正执行后,调用AfterProceedAsync.通过hasAsynResult可判断是否有返回值.

如果有返回值也可通过ProceedAsynResult读取或修改所拦截方法的最终返回值.

对于此问题的其他拦截器实现方法的代码样例,可参照代码:https://github.com/wswind/Learn-AOP/tree/master/AutofacAsyncInterceptor-More

.net core autofac asyncinterceptor 异步拦截器帮助包的更多相关文章

  1. .net core autofac asyncinterceptor 异步拦截器开发

    autofac使用拦截器实现AOP,是基于Castle.Core的.然而Castle.Core并未提供原生异步支持.所以需要使用帮助类实现,这在autofac官方文档的已知问题中有详细说明: http ...

  2. ASP.NET Core搭建多层网站架构【9.2-使用Castle.Core实现动态代理拦截器】

    2020/01/31, ASP.NET Core 3.1, VS2019, Autofac.Extras.DynamicProxy 4.5.0, Castle.Core.AsyncIntercepto ...

  3. ASP.NET Core 3.0 gRPC 拦截器

    目录 ASP.NET Core 3.0 使用gRPC ASP.NET Core 3.0 gRPC 双向流 ASP.NET Core 3.0 gRPC 拦截器 一. 前言 前面两篇文章给大家介绍了使用g ...

  4. 014-Spring Boot web【三】拦截器HandlerInterceptor、异常处理页面,全局异常处理ControllerAdvice

    一.拦截器HandlerInterceptor 1.1.HandlerInterceptor接口说明 preHandle,congtroller执行前,如果返回false请求终端 postHandle ...

  5. SpringMVC之八:基于SpringMVC拦截器和注解实现controller中访问权限控制

    SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法. preHandle在业务处理器 ...

  6. 源码解析Grpc拦截器(C#版本)

    前言 其实Grpc拦截器是我以前研究过,但是我看网上相关C#版本的源码解析相对少一点,所以笔者借这篇文章给大家分享下Grpc拦截器的实现,废话不多说,直接开讲(Grpc的源码看着很方便,包自动都能还原 ...

  7. struts2:拦截器

    拦截器(Interceptor)是Struts 2的核心组件,Struts 2框架的大部分功能都是通过拦截器来完成的,例如数据校验,国际化,文件上传和下载等.为了实现这些功能,Struts 2框架提供 ...

  8. Web系统Login拦截器

    所需要导入的包类:import org.springframework.web.servlet.HandleInterceptor;(拦截器要继承该类) public class loginInter ...

  9. 第十篇——Struts2的拦截器栈

    拦截器栈: 从结构上看:拦截器栈相当于多个拦截器的组合: 从功能上看:拦截器栈也是拦截器. 默认拦截器栈: 在struts-core.jar包中的struts-default.xml中自定义了一个de ...

随机推荐

  1. JAVA8--流处理和optional

    转载自https://www.cnblogs.com/invoker-/p/6896865.html 流与集合    众所周知,日常开发与操作中涉及到集合的操作相当频繁,而java中对于集合的操作又是 ...

  2. python基础入门语法和变量类型(二)

    列表 列表是 Python 中使用最频繁的数据类型,它可以完成大多数集合类的数据结构实现,可以包含不同类型的元素,包括数字.字符串,甚至列表(也就是所谓的嵌套). 和字符串一样,可以通过索引值或者切片 ...

  3. java 并发线程池的理解和使用

    一.为什么要用线程池 合理利用线程池能够带来三个好处. 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立 ...

  4. Linux系统编程—条件变量

    条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用.条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等 ...

  5. Centos-搜索文件或目录-find

    find 在指定的目录下查找指定的文件 相关选项 -type 指定文件类型 -name   指定文件名字,支持通配符 -gid   指定用户组ID -uid   指定用户ID -empty 查找长度为 ...

  6. Java学习day05

    Java学习day05 [switch]属于选择结构,分支语句 语法结构: /* switch(int或string类型字面值或变量) { case int或string类型字面值或变量 : java ...

  7. 【题解】[USACO08MAR]Land Acquisition G

    Link 题目大意:给定\(n\)个二元组,每次可以选择一组,花费是组内最大的长乘以最大的宽.问消掉所有二元组的最小代价. \(\text{Solution:}\) \(dp\)写的不够啊-- 先挖掘 ...

  8. 最全153道Spring全家桶面试题,你都碰到过哪些?(含答案解析)

    前言 Spring 框架自诞生以来一直备受开发者青睐,有人亲切的称之为:Spring 全家桶. 毋庸置疑,Spring 早已成为 Java 后端开发的行业标准,无数的公司选择 Spring 作为基础的 ...

  9. 在Linux下如何根据域名自签发OpenSSL证书与常用证书转换

    在Linux下如何根据域名自签发各种SSL证书,这里我们以Apache.Tomcat.Nginx为例. openssl自签发泛域名(通配符)证书 首先要有openssl工具,如果没有那么使用如下命令安 ...

  10. MySQL 之 innodb 日志管理 -- 1. 基本日志文件

    1.基本日志文件分类 错误日志(error log) 慢查询日志日志(slow query log) 二进制日志(binlog) 查询日志(general log) 2.错误日志 主要包括mysql的 ...