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. concurrent.futures模块简单介绍(线程池,进程池)

    一.基类Executor Executor类是ThreadPoolExecutor 和ProcessPoolExecutor 的基类.它为我们提供了如下方法: submit(fn, *args, ** ...

  2. 高效取余运算(n-1)&hash原理探讨

    Java的HashMap源码中用到的(n-1)&hash这样的运算,查找发现这是一种高效的求余数的办法,但其中的原理是什么呢为什么可以这么做呢? 先上结论:假设被除数是x,对于除数是2n的取余 ...

  3. 解决pip使用异常No module named 'pip'

    场景 在使用pip进行升级时 python install --upgrade named pip 时提示: No module named pip 注: 博客: https://blog.csdn. ...

  4. SSM框架之Mybatis(4)SqlMapConfig

    Mybatis(4)SqlMapConfig.xml SqlMapConfig.xml 中配置的内容和顺序 -properties (属性) --property -settings(全局配置参数) ...

  5. 关于es6及以上的js编译成es5

    问题:es6及以上版本在IE浏览器上不能执行起来,但Chrome浏览器上轻松运行,解决兼容IE的问题就需要使用babel:这个可以去babel的官网去查看; 关于babel的简单使用,有两种方式: 1 ...

  6. Go命令行库Cobra的核心文件root.go

    因为docker及Kubernetes都在用cobra库,所以记录一下. 自定义的地方,高红标出. root.go /* Copyright © 2019 NAME HERE <EMAIL AD ...

  7. if选择结构

    if的语法规则: if(布尔表达式){java语句} //只有一个java语句的时候可以省略大括号不建议这么写但是别人写的代码能看懂 if的写法有4种: if(){} if(){}else{} if( ...

  8. day65_10_9vue循环指令与组件

    一.v-once v-once指令赋值给标签后,这个标签中的所有变量都不能被更改,只能被渲染一次.之后的改动不能改变该标签中的值: <div id="app"> < ...

  9. C++ 标准库 std::remove

    参见:https://zh.cppreference.com/w/cpp/algorithm/remove std::remove 不会改变输入vector / string 的长度.其过程,相当于去 ...

  10. 第七周第二次Scrum会议

    工作: 根据上个周对前端的布置学习,布置大家开发了相应的界面.(界面开发成果写在测试报告) 地点: 二餐二 会议照片: 忘记拍了... 核心问题: 如何编写统一风格的前端界面. 解决: 将相应资源打包 ...