AspectCore是适用于Asp.Net Core 平台的轻量级Aop(Aspect-oriented programming)解决方案,它更好的遵循Asp.Net Core的模块化开发理念,使用AspectCore可以更容易构建低耦合、易扩展的Web应用程序。

在使用过程中,由于相关文档、博客还未更新到.Net Core 3.0,本文操作参考了使用.Net Core 3.0的EasyCaching,并对其中公用的方法进行封装简化。

安装Aspectcore

此处配合微软自家的DI实现,安装Nuget包AspectCore.Extensions.DependencyInjection,其中包含AspectCore.Core和Microsoft.Extensions.DependencyInjection两个依赖。

Install-Package AspectCore.Extensions.DependencyInjection -Version 1.3.0

拦截器

  • 特性拦截器

    新建一个特性拦截器TestInterceptorAttribute,继承AbstractInterceptorAttribute,并重写Invoke方法,在方法中实现拦截相关业务。
public class TestInterceptorAttribute : AbstractInterceptorAttribute
{
public override Task Invoke(AspectContext context, AspectDelegate next)
{
return context.Invoke(next);
}
}
  • 全局拦截器

    新建一个全局拦截器TestInterceptor,继承AbstractInterceptor,并重写Invoke方法,在方法中实现拦截相关业务。
public class TestInterceptor : AbstractInterceptor
{
public override Task Invoke(AspectContext context, AspectDelegate next)
{
return context.Invoke(next);
}
}

注册服务

以下注册方式仅适用于asp.net core 3.0(目前只到3.0),已知在2.2版本中,需要在ConfigureServices方法中返回IServiceProvider,并且program.cs中也不再需要替换ServiceProviderFactory。

1.创建AspectCoreEctensions.cs扩展IServiceCollection

public static class AspectCoreExtensions
{
public static void ConfigAspectCore(this IServiceCollection services)
{
services.ConfigureDynamicProxy(config =>
{
//TestInterceptor拦截器类
//拦截代理所有Service结尾的类
config.Interceptors.AddTyped<TestInterceptor>(Predicates.ForService("*Service"));
});
services.BuildAspectInjectorProvider();
}
}

2.在Startup.cs中注册服务

public void ConfigureServices(IServiceCollection services)
{
services.ConfigAspectCore();
}

3.在Program.cs中替换ServiceProviderFactory

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseServiceProviderFactory(new AspectCoreServiceProviderFactory());

被拦截方法编写

  • 代理接口:在接口上标注Attribute
public interface ITestService
{
[TestInterceptor]
void Test();
}
  • 代理类(方法):在方法上标注Attribute,并且标注virtual
public class TestService
{
[TestInterceptor]
public virtual void Test()
{
//业务代码
}
}

拦截器业务编写

  • 执行被拦截方法
private async Task<object> RunAndGetReturn()
{
await Context.Invoke(Next);
return Context.IsAsync()
? await Context.UnwrapAsyncReturnValue()
: Context.ReturnValue;
}
  • 拦截器中的依赖注入
[FromContainer]
private RedisClient RedisClient { get; set; }
  • 获取被拦截方法的Attribute
private static readonly ConcurrentDictionary<MethodInfo, object[]>
MethodAttributes = new ConcurrentDictionary<MethodInfo, object[]>(); public static T GetAttribute<T>(this AspectContext context) where T : Attribute
{
MethodInfo method = context.ServiceMethod;
var attributes = MethodAttributes.GetOrAdd(method, method.GetCustomAttributes(true));
var attribute = attributes.FirstOrDefault(x => typeof(T).IsAssignableFrom(x.GetType()));
if (attribute is T)
{
return (T)attribute;
}
return null;
}
  • 获取被拦截方法返回值类型
public static Type GetReturnType(this AspectContext context)
{
return context.IsAsync()
? context.ServiceMethod.ReturnType.GetGenericArguments()First()
: context.ServiceMethod.ReturnType;
}
  • 处理拦截器返回结果
private static readonly ConcurrentDictionary<Type, MethodInfo>
TypeofTaskResultMethod = new ConcurrentDictionary<Type, MethodInfo>();
public object ResultFactory(this AspectContext context,object result)
{
var returnType = context.GetReturnType(); //异步方法返回Task<T>类型结果
if (context.IsAsync())
{
return TypeofTaskResultMethod
.GetOrAdd(returnType, t => typeof(Task)
.GetMethods()
.First(p => p.Name == "FromResult" && p.ContainsGenericParameters)
.MakeGenericMethod(returnType))
.Invoke(null, new object[] { result });
}
else
{
return result;
}
}

相关链接

ASP.NET Core 3.0 使用AspectCore-Framework实现AOP的更多相关文章

  1. ASP.NET Core 1.0: Using Entity Framework Core

    伴随着ASP.NET Core 1.0发布的还有Entity Framework Core 1.0; 官方文档链接:https://docs.efproject.net/en/latest/platf ...

  2. 打造静态分析器(二)基于Asp.Net Core 3.0的AspectCore组件检测

    上一篇,我们打造了一个简单的分析器,但是我们实际使用分析器就是为了对项目做分析检测,增加一些非语法的自检的 比如Asp.Net Core 3.0的替换依赖注入检测 设计分析 我们创建一个默认的Asp. ...

  3. [转]ASP.NET Core 1.0: Using Entity Framework Core 1.0 - Transaction

    本文转自:http://blog.csdn.net/alvachien/article/details/51576961 跟Entity Framework之前的版本不同,Class DbContex ...

  4. ASP.NET Core 1.0: Using Entity Framework Core 1.0 - Transaction

    跟Entity Framework之前的版本不同,Class DbContext不再有AcceptAllChanges()方法. 使用Transaction需要使用DbContext中的Databas ...

  5. ASP.NET Core 1.0、ASP.NET MVC Core 1.0和Entity Framework Core 1.0

    ASP.NET 5.0 将改名为 ASP.NET Core 1.0 ASP.NET MVC 6  将改名为 ASP.NET MVC Core 1.0 Entity Framework 7.0    将 ...

  6. [转帖]2016年时的新闻:ASP.NET Core 1.0、ASP.NET MVC Core 1.0和Entity Framework Core 1.0

    ASP.NET Core 1.0.ASP.NET MVC Core 1.0和Entity Framework Core 1.0 http://www.cnblogs.com/webapi/p/5673 ...

  7. .NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布

    众所周知,Red Hat和微软正在努力使.NET Core成为Red Hat企业版Linux (RHEL)系统上的一流开发平台选项.这个团队已经一起工作好几个月了,RHEL对.NET有许多需求.今天在 ...

  8. .NET Core & ASP.NET Core 1.0

    .NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布 众所周知,Red Hat和微软正在努力使.NET Core成为Red Hat企业版Linux (RHEL) ...

  9. .NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0简介

    .NET Core 1.0.ASP.NET Core 1.0和EF Core 1.0简介 英文原文:Reintroducing .NET Core 1.0, ASP.NET Core 1.0, and ...

  10. [争什么! 掺在一起做撒尿牛丸啊! 笨蛋]ASP.NET Core 2.0 + EF6 + Linux +MySql混搭

    好消息!特好消息!同时使用ASP.NET Core 2.0和.NET Framework类库还能运行在linux上的方法来啦! 是的,你没有看错!ASP.NET Core 2.0,.NET Frame ...

随机推荐

  1. 初学Python常见异常错误,总有一处你会遇到!

    初学Python常见错误 忘记写冒号 误用= 错误 缩紧 变量没有定义 中英文输入法导致的错误 不同数据类型的拼接 索引位置问题 使用字典中不存在的键 忘了括号 漏传参数 缺失依赖库 使用了pytho ...

  2. 转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼

    简介 想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了. 这是一个能让你了解自己的浏览历史的Chrome浏览历史记录分析程序,当然了,他仅 ...

  3. golang中type常用用法

    golang中,type是非常重要的关键字,一般常见用法就是定义结构,接口等,但是type还有很多其它的用法,在学习中遇到了以下几种,这点简单总结记录下 定义结构 type Person struct ...

  4. python 计算 对象 占用大小

    # 这里主要是计算文件内容(str)的大小即: 统计空间占用情况, 并转换宜读单位 K,M def gen_atta_size(con): # 参数可以是任意数据类型 if con: size_b = ...

  5. 移动OA办公——Smobiler第一个开源应用解决方案,快来get吧

    产品简介 SmoONE是一款移动OA类的开源解决方案,通过Smobiler平台开发,包含了注册.登陆.用户信息等基本功能.集成了OA中使用场景较多的报销.请假.部门管理.成本中心等核心功能. 免费获取 ...

  6. react相关小技巧

    一.我们在项目中切换路由的时候可能会遇到 Warning: setState(...): Can only update a mounted or mounting component. This u ...

  7. k8s中的client-go编译成功

    要分版本的,好像1.4跟12差别好大. 1.4中用的模块管理还是vendor,12就换成mod了. 这个要记住差异. 一,从github上下载client-go的1.4版本 https://githu ...

  8. python time和datetime常用写法格式

    python 的time和datetime常用写法 import time from datetime import datetime from datetime import timedelta # ...

  9. Mybatis环境搭建(二)

    1. 创建Maven Project,选择war,修改pom.xml <properties> <!-- JDK版本 --> <java.version>1.8&l ...

  10. 剑指Offer-18.二叉树的镜像(C++/Java)

    题目: 题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ ...