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. 初识Lock与AbstractQueuedSynchronizer(AQS)

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  2. python凯撒加密

    在密码学中,恺撒密码是一种最简单且最广为人知的加密技术.它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文.例,当偏移量是3的时候,所有的字母A将 ...

  3. Incorrect datetime value: '' for column 'examDate' at row 1

    出问题的程序:user.setCreateTime(new Date()); 控制台图片一张,问题是:Incorrect datetime value: '' for column 'createTi ...

  4. 批量bat脚本复制文件或文件夹

    主要用于在本地下,复制文件或文件夹到当前文件夹 @echo off echo 复制文件或文件夹到当前文件夹(复制文件选择[],复制文件夹选择[]) set /p num=输入选择的数字: : set ...

  5. xposed 原理分析

    1.添加hook方法 首先是init进程打开 app_process,然后进入XposedInit.java main() - > initForZygote() 加入对ActivityThre ...

  6. 自定义MVC三

    完成t_mvc_book表的增删改查1.通用分页的jar.自定义mvc框架.自定义标签 导入jar.导入之前写好的pageTag.自定义mvc.xml pageTag private static f ...

  7. 19.Java基础_封装概念

  8. 使用Fiddler模拟弱网测试教程

    一.下载抓包工具Fiddler 官网下载链接:https://www.telerik.com/fiddler 二.设置Fiddler Tools>>Connections  然后修改监听端 ...

  9. Vue的实例对象(三)

    一.创建一个 Vue 实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 当创建一个 Vue 实例时,你可以传入 ...

  10. Log日志级别从高到低排序 ERROR、WARN、INFO、DEBUG

    Log4j建议只使用四个级别,优先级从高到低分别是 ERROR.WARN.INFO.DEBUG.通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关.比如在这里定义了INFO级别,则应 ...