FluentAspects -- 基于 Fluent API 的 Aop
FluentAspects -- 基于 Fluent API 的 Aop
Intro
上次我们做了一个简单的 AOP 实现示例,但是实现起来主要是基于 Attribute
来做的,对于代码的侵入性太强,于是尝试实现基于 Fluent API 的方式来做 AOP 。
抽象 InterceptorResolver
原来获取方法执行的 Interceptor 是通过 Attribute
来获取的,现在我们只需要将获取 Interceptor 的逻辑抽象出来就可以实现不必依赖于 Attribute
了
方法执行上下文定义:
public interface IInvocation
{public MethodInfo ProxyMethod { get; }public object ProxyTarget { get; }public MethodInfo Method { get; }public object Target { get; }public object[] Arguments { get; }Type[] GenericArguments { get; }public object ReturnValue { get; set; }
}
方法拦截器 Interceptor
接口定义:
public interface IInterceptor
{Task Invoke(IInvocation invocation, Func<Task> next);
}
自定义 Interceptor 只需要继承这个接口实现相应的逻辑就好了
获取 IInterceptorResolver
接口定义:
public interface IInterceptorResolver
{IReadOnlyCollection<IInterceptor> ResolveInterceptors(IInvocation invocation);
}
原来基于 Attribute
获取 Interceptor 的方式可以实现一个 AttributeInterceptorResolver
想要基于 Fluent API 来获取 Interceptor ,只需要实现基于 Fluent API 的 InterceptorResolver
就可以了,具体的实现可以参考 FluentConfigInterceptorResolver
示例预览
测试服务定义:
public interface ISvc1
{void Invoke();
}
public interface ISvc2
{void Invoke();
}
public class Svc2 : ISvc2
{public void Invoke(){Console.WriteLine($"invoking in {GetType().Name} ...");}public void Invoke2(){Console.WriteLine($"invoking in {GetType().Name} ...");}
}
public class Svc3
{public virtual void Invoke(){Console.WriteLine($"invoking in {GetType().Name} ...");}
}
public class Svc4
{public virtual void Invoke(){Console.WriteLine($"invoking in {GetType().Name} ...");}public void Invoke2(){Console.WriteLine($"invoking2 in {GetType().Name} ...");}public virtual void Invoke3(){Console.WriteLine($"invoking3 in {GetType().Name} ...");}
}
测试 Interceptor
internal class LogInterceptor : IInterceptor
{public async Task Invoke(IInvocation invocation, Func<Task> next){Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} begin");await next();Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} end");}
}
测试代码:
public static void Main(string[] args)
{var services = new ServiceCollection();services.AddFluentAspects(options =>{// 为所有拦截的方法添加拦截器options.InterceptAll().With<LogInterceptor>();// 对 Svc3 类型禁用拦截器options.NoInterceptType<Svc3>();// Svc4 类型的 Invoke3() 方法禁用拦截器options.NoInterceptMethod<Svc4>(s => s.Invoke3());});services.AddTransientProxy<Svc4>();var serviceProvider = services.BuildServiceProvider();var proxyFactory = serviceProvider.GetRequiredService<IProxyFactory>();var svc1 = proxyFactory.CreateProxy<ISvc1>();svc1.Invoke();Console.WriteLine();var svc2 = proxyFactory.CreateProxy<ISvc2, Svc2>();svc2.Invoke();Console.WriteLine();var svc3 = proxyFactory.CreateProxy<Svc3>();svc3.Invoke();Console.WriteLine();var svc4 = proxyFactory.CreateProxyWithTarget<ISvc2, Svc2>(new Svc2());svc4.Invoke();Console.WriteLine();// 直接从注册的服务中获取var svc5 = serviceProvider.GetRequiredService<Svc4>();svc5.Invoke();Console.WriteLine();svc5.Invoke2();Console.WriteLine();svc5.Invoke3();Console.WriteLine();Console.WriteLine("finished");Console.ReadLine();
}
输出结果预览:
More
最近十几天的时间一直在搞这个,相比之前写的示例,真正实现一个完整的 AOP 框架还是要做比较多的事情的,之前的 AOP 示例,没有考虑泛型,也没有什么设计,所以前面的示例只能算是一个小玩具。
在实现的过程中,参考了很多 AspectCore 的代码,有一些代码甚至是直接从 AspectCore 里抄过来的。
推荐大家有机会研究学习一下柠檬大佬的 AspectCore 的源码,这个 AOP 框架的代码组织,代码细节都挺不错的。
AspectCore 源码地址:https://github.com/dotnetcore/AspectCore-Framework
Reference
https://github.com/WeihanLi/WeihanLi.Common/tree/dev/src/WeihanLi.Common/Aspect
https://github.com/WeihanLi/SamplesInPractice/blob/master/FluentAspectSample/Program.cs
https://github.com/dotnetcore/AspectCore-Framework
FluentAspects -- 基于 Fluent API 的 Aop相关推荐
- Fluent API — 流畅API(基于Java介绍)
Fluent API ,流畅API, 也称作流式API. Fluent API 是一种面向对象的API,主要基于方法链. 这个概念由Eric Evans和Martin Fowler于 2005 ...
- 实现一个基于动态代理的 AOP
实现一个基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的,后面有 ...
- FreeSql (四)实体特性 Fluent Api
FreeSql 提供使用 Fluent Api, 在外部配置实体的数据库特性,Fluent Api 的方法命名与特性名保持一致,如下: fsql.CodeFirst.ConfigEntity<T ...
- thinkcmf5调用指定分类的二级_Tengine快速上手系列教程amp;视频:基于Python API的图片分类应用入门丨附彩蛋...
前言:近期,Tengine团队加班加点,好消息接踵而来,OpenCV 4.3.0发布,OPEN AI LAB AIoT智能开发平台Tengine与OpenCV合作共同加速边缘智能,Tengine再获业 ...
- 你也可以玩转Skype -- 基于Skype API开发外壳程序入门
原文:你也可以玩转Skype -- 基于Skype API开发外壳程序入门 Skype是目前这个星球上最厉害的IM+VOIP软件,Skype现在已经改变了全球2.8亿人的生活方式.你,值得拥有! :) ...
- Spring3基于注释驱动的AOP
51CTO正在组织十佳博客评选请 Spring3基于注释驱动的AOP 实在是郁闷刚刚编辑了一篇文章,由于字数的原因,没发布成功,好我就分开写吧,今天向大家介绍的是Spring基于注释驱动的AOP,其实 ...
- 基于Winsock API的VC网络编程实战
基于Winsock API的VC网络编程实战 随着计算机信息技术的飞速发展,互联网与人类社会的工作.生活越来越紧密相关,它已经成为人类获取.交流信息的重要途径和手段.所以当前对于开发人员来说,网络编程 ...
- EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射
为什么80%的码农都做不了架构师?>>> EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 I.EF里的默认映射 上篇文章演示 ...
- 基于ArcGIS API for JavaScript加载天地图
文章目录 前言 效果图 详细代码 总结 参考链接 前言 该篇主要介绍如何用ArcGIS JS API加载天地图,具体应用场景以及需求分析等,在上篇基于ArcGIS API for JavaScript ...
最新文章
- 多视图立体匹配论文分享:BlendedMVS
- 南云等PNAS研究论文:揭示儿童音乐学习向语言领域迁移的脑机制
- HBase基本概念和hbase shell常用命令用法
- AI:神经网络调参(数据、层数、batch大小,学习率+激活函数+正则化+分类/回归)并进行结果可视化
- 利用CSS设置页面的垂直居中效果
- 机器学习_机器不学习:从Spark MLlib到美图机器学习框架实践
- k8s边缘节点_边缘计算,如何啃下集群管理这块硬骨头?
- 【转】对路径**的访问被拒绝
- pytorch 中nn.MaxPool1d() 和nn.MaxPool2d()对比;nn.functional.max_pool1d
- Java学习不走弯路教程(16 用Ajava异步请求)
- chrome 开启HEVC硬件解码
- 如何利用excel中的数据源制作数据地图
- javascript之键盘事件
- 微信小程序:map组件的简单使用,标注callout与label简单用法
- Oracle 12C 基础知识与使用入门(修订版)
- 手机删掉的照片怎么恢复
- 【洛谷 P7299】 【并查集】 Dance Mooves S
- idea设置类注释和方法注释模板
- 【STM32F407开发板用户手册】第7章 STM32F407下载和调试方法(IAR8)
- 教师资格证报名显示内核服务器错误,中小学教师资格证报考支付卡状态失效是怎么回事?..._教师资格考试_帮考网...
热门文章
- 2.2 PostgreSQL 概念
- python 生成排列、组合以及选择
- C# 使用int.TryParse,Convert.ToInt32,(int)将浮点类型转换整数时的区别
- 在php中使用sockets:从新闻组中获取文章
- jQuery Pagination Ajax分页插件中文详解
- 共享没有权限访问权限_如何与家人共享SmartThings访问权限
- 【Redis源码分析】Redis命令处理生命周期
- 大数据在金融领域的应用及问题时
- 同一个PC只能运行一个应用实例(考虑多个用户会话情况)
- linux下ip命令用法