(转).NET Core中实现AOP编程
原文地址:https://www.cnblogs.com/xiandnc/p/10088159.html
AOP全称Aspect Oriented Progarmming(面向切面编程),其实AOP对ASP.NET程序员来说一点都不神秘,你也许早就通过Filter来完成一些通用的功能,例如你使用Authorization Filter来拦截所有的用户请求,验证Http Header中是否有合法的token。或者使用Exception Filter来处理某种特定的异常。
你之所以可以拦截所有的用户请求,能够在期望的时机来执行某些通用的行为,是因为ASP.NET
Core在框架级别预留了一些钩子,他允许你在特定的时机注入一些行为。对ASP.NET Core应用程序来说,这个时机就是HTTP请求在执行MVC
Action的中间件时。

显然这个时机并不能满足你的所有求,比如你在Repository层有一个读取数据库的方法:
|
1
2
3
4
|
public void GetUser(){ //Get user from db} |
你试图得到该方法执行的时间,首先想到的方式就是在整个方法外面包一层用来计算时间的代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public void GetUserWithTime(){ var stopwatch = Stopwatch.StartNew(); try { //Get user from db } finally { stopwatch.Stop(); Trace.WriteLine("Total" + stopwatch.ElapsedMilliseconds + "ms"); }} |
如果仅仅是为了得到这一个方法的执行时间,这种方式可以满足你的需求。问题在于你有可能还想得到DeleteUser或者UpdateUser等方法的执行时间。修改每一个方法并添加计算时间的代码存在着明显的code smell。
一个比较优雅的做法是给需要计算时间的方法标记一个Attribute:
|
1
2
3
4
5
|
[Time]public void GetUser(){ //Get user from db} |
你把计算时间这个功能当做一个切面(Aspect)注入到了现有的逻辑中,这是一个AOP的典型应用。
在C#中使用AOP
C#中可以用来做AOP的开源类库有若干个,比较流行的:
这些类库之所以能够实现AOP是因为他们有动态修改IL代码的能力,这种能力又被称为IL weaving。
还有的类库把AOP和Dependency Injection结合在了一起,通过服务上注册一个拦截器(Interceptor)的方式做达到AOP的目的,例如:
本文将使用一个C#开源项目aspect-injector来描述AOP的几种常见的场景。
aspect-injector是一个非常轻量级的AOP类库,麻雀虽小,但是已经能够应对大部分AOP的应用场景:
- 支持.NET Core
- 支持对异步方法注入切面
- 能够把切面注入到方法、属性和事件上
- 支持Attribute的方式注入切面
注入计算执行时间的逻辑
在已有的方法上注入一段逻辑可以分为三种情况:
- 在方法执行前注入一段逻辑,例如注入统一的认证逻辑
- 在方法执行后注入一段逻辑,例如将结果写入日志
- 方法前后同时注入逻辑,例如计算时间,又或者给整个方法内容包裹一个事务
已知一个计算个数的方法如下:
|
1
2
3
4
5
6
7
8
|
public class SampleService{ public int GetCount() { Thread.Sleep(3000); return 10; }} |
为了将计算时间的逻辑包裹在现有的方法上,我们需要在被注入逻辑的方法上标记InjectAttribute:
|
1
2
3
4
5
6
7
8
9
|
public class SampleService{ [Inject(typeof(TimeAspect))] public int GetCount() { Thread.Sleep(3000); return 10; }} |
TimeAspect就是我们将要注入的一个切面:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
[Aspect(Aspect.Scope.Global)]public class TimeAspect { [Advice(Advice.Type.Around, Advice.Target.Method)] public object HandleMethod( [Advice.Argument(Advice.Argument.Source.Name)] string name, [Advice.Argument(Advice.Argument.Source.Arguments)] object[] arguments, [Advice.Argument(Advice.Argument.Source.Target)] Func<object[], object> method) { Console.WriteLine($"Executing method {name}"); var sw = Stopwatch.StartNew(); var result = method(arguments); //调用被注入切面的方法 sw.Stop(); Console.WriteLine($"method {name} in {sw.ElapsedMilliseconds} ms"); return result; } } |
大部分代码是非常清晰的,我们只描述几个重要的概念:
标记了AdviceAttribute的方法就是即将要注入到目标方法的切面逻辑,也就是说HandleMethod描述了如何计算时间。
Advice.Type.Around描述了同时在目标方法的前后都注入逻辑
方法参数Func<object[], object> method其实就代表目标方法
注入认证逻辑
试想你有如果干个服务,每个服务在执行前都要做安全认证,显然安全认证的逻辑是可重用的,那我们就可以把认证的逻辑提取成一个切面(Aspect)。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[Inject(typeof(AuthorizationAspect))]public class SampleService{ public void MethodA(Guid userId) { // Do something } public void MethodB(Guid userId) { // Do something }} |
AuthorizationAspect就是安全认证的逻辑:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
[Aspect(Aspect.Scope.Global)]public class AuthorizationAspect{ [Advice(Advice.Type.Before, Advice.Target.Method)] public void CheckAccess( [Advice.Argument(Advice.Argument.Source.Method)] MethodInfo method, [Advice.Argument(Advice.Argument.Source.Arguments)] object[] arguments) { if (arguments.Length == 0 || !(arguments[0] is Guid)) { throw new ArgumentException($"{nameof(AuthorizationAspect)} expects every target method to have Guid as the first parameter"); } var userId = (Guid)arguments[0]; if (!_securityService.HasPermission(userId, authorizationAttr.Permission)) { throw new Exception($"User {userId} doesn't have permission to execute method {method.Name}"); } }} |
Advice.Type.Before描述了该逻辑会在被修改的方法前执行
通过object[] arguments得到了被修改方法的所有参数
AOP是面向对象编程中一种用来抽取公用逻辑,简化业务代码的方式,灵活使用AOP可以让你的业务逻辑代码不会过度臃肿,也是除了继承之外另一种可复用代码的方式。
aspect-injector地址:https://github.com/pamidur/aspect-injector/tree/master/docs#this
(转).NET Core中实现AOP编程的更多相关文章
- .NET Core中实现AOP编程
AOP全称Aspect Oriented Progarmming(面向切面编程),其实AOP对ASP.NET程序员来说一点都不神秘,你也许早就通过Filter来完成一些通用的功能,例如你使用Autho ...
- [翻译]在 .NET Core 中的并发编程
原文地址:http://www.dotnetcurry.com/dotnet/1360/concurrent-programming-dotnet-core 今天我们购买的每台电脑都有一个多核心的 C ...
- .NET Core 中的并发编程
今天我们购买的每台电脑都有一个多核心的 CPU,允许它并行执行多个指令.操作系统通过将进程调度到不同的内核来发挥这个结构的优点. 然而,还可以通过异步 I/O 操作和并行处理来帮助我们提高单个应用程序 ...
- 聊Javascript中的AOP编程
Duck punch 我们先不谈AOP编程,先从duck punch编程谈起. 如果你去wikipedia中查找duck punch,你查阅到的应该是monkey patch这个词条.根据解释,Mon ...
- 聊聊Javascript中的AOP编程
Duck punch 我们先不谈AOP编程,先从duck punch编程谈起. 如果你去wikipedia中查找duck punch,你查阅到的应该是monkey patch这个词条.根据解释,Mon ...
- 在ASP.NET Core中使用AOP来简化缓存操作
前言 关于缓存的使用,相信大家都是熟悉的不能再熟悉了,简单来说就是下面一句话. 优先从缓存中取数据,缓存中取不到再去数据库中取,取到了在扔进缓存中去. 然后我们就会看到项目中有类似这样的代码了. pu ...
- .NET下集中实现AOP编程的框架
一.Castle 使用这个框架呢,首先是需要安装NuGet包. 先建立一个控制台项目,然后在NuGet中搜索Castle.Windsor,不出意外的话应该能找到如下的包 然后安装,会自动的安装包Cas ...
- [译]如何在ASP.NET Core中实现面向切面编程(AOP)
原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
随机推荐
- [原创]STAR法则
[原创]STAR法则 STAR法则是情境(situation).任务(task).行动(action).结果(result)四项的缩写. STAR法则是一种常常被面试官使用的工具,用来收集面试者与工作 ...
- 2018-2019-2 20175211 实验四《Android程序设计》实验报告
目录 一.实验内容及步骤 1.Android Studio的安装测试 2.Activity测试 3.UI测试 4.布局测试 5.事件处理测试 二.问题及解决方法 三.代码托管 四.实验心得体会 一.实 ...
- CSS Blur() 将高斯模糊应用于输出图片
一.Css Blur() blur() CSS 方法将高斯模糊应用于输出图片. 结果为 <filter-function>. blur(radius) radius模糊的半径,值为< ...
- android中SELINUX规则分析和语法简介
1. SELINUX是可以理解为一种android上面的安全机制,是有美国国家安全局和一些公司设计的一个针对linux的安全加强系统我们可以通过配置SELINUX的相关policy,来定制自己的手机的 ...
- C++ std::map 屏蔽排序
转载:https://blog.csdn.net/sendinn/article/details/96286849 最近在项目中用标准库中的关联性容器map,但知道map默认升序的,但在一个需求时又不 ...
- libFFM 与 python-libffm 安装遇到的一系列问题-解决方案
mac os x 环境下 libFFM 与 python-libffm的安装问题 Gcc 版本问题 : brew Clang 版本问题 : brew upgrade llvm 编译参数: 多核运行 o ...
- 一行命令搞定/usr/bin/perl^M: bad interpreter
https://www.cnblogs.com/albertYe/p/8819143.html **************************************************** ...
- CentOS7下的CDH 6.2.0 安装过程
#install OS centos 7.5#install lsb packageyum install -y redhat-lsb #install net-tools package yum i ...
- (转)How To Create a Sudo User on Ubuntu
转自:https://linuxize.com/post/how-to-create-a-sudo-user-on-ubuntu/ The sudo command is designed to al ...
- asp.net msbuild 发布
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\msbuild.exe ...