.NET Core中实现AOP编程
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层有一个读取数据库的方法:
public void GetUser()
{
//Get user from db
}
你试图得到该方法执行的时间,首先想到的方式就是在整个方法外面包一层用来计算时间的代码:
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:
[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的方式注入切面
注入计算执行时间的逻辑
在已有的方法上注入一段逻辑可以分为三种情况:
- 在方法执行前注入一段逻辑,例如注入统一的认证逻辑
- 在方法执行后注入一段逻辑,例如将结果写入日志
- 方法前后同时注入逻辑,例如计算时间,又或者给整个方法内容包裹一个事务
已知一个计算个数的方法如下:
public class SampleService
{
public int GetCount()
{
Thread.Sleep(3000);
return 10;
}
}
为了将计算时间的逻辑包裹在现有的方法上,我们需要在被注入逻辑的方法上标记InjectAttribute:
public class SampleService
{
[Inject(typeof(TimeAspect))]
public int GetCount()
{
Thread.Sleep(3000);
return 10;
}
}
TimeAspect就是我们将要注入的一个切面:
[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)。
[Inject(typeof(AuthorizationAspect))]
public class SampleService
{
public void MethodA(Guid userId)
{
// Do something
}
public void MethodB(Guid userId)
{
// Do something
}
}
AuthorizationAspect就是安全认证的逻辑:
[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可以让你的业务逻辑代码不会过度臃肿,也是除了继承之外另一种可复用代码的方式。
.NET Core中实现AOP编程的更多相关文章
- (转).NET Core中实现AOP编程
原文地址:https://www.cnblogs.com/xiandnc/p/10088159.html AOP全称Aspect Oriented Progarmming(面向切面编程),其实AOP对 ...
- [翻译]在 .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 ...
随机推荐
- Zathura: 轻巧好用的 PDF 查看器]
[Zathura: 轻巧好用的 PDF 查看器](https://linuxtoy.org/archives/zathura.html) 这个文件很轻巧,且支持VIM方式的 快捷键
- 对象关系映射 ORM
1.1 作用 MTV框架中包括一个重要的部分,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因 ...
- 洛谷P3802:小魔女帕琪
题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从而唱出强力的魔法.比如说 ...
- 将普通用户添加到sudo
将普通用户添加到sudo组 可以编辑/etc/sudoers文件将普通用户加入sudo组.要注意的是修改该文件只能使用visudo命令:1.首先切换到root #su - (注意有 “-” ,这和su ...
- pta-树种统计
树种统计 (25 分) 随着卫星成像技术的应用,自然资源研究机构可以识别每一棵树的种类.请编写程序帮助研究人员统计每种树的数量,计算每种树占总数的百分比. 输入格式: 输入首先给出正整数N(≤105 ...
- 《SpringMVC从入门到放肆》七、模型与视图ModelAndView
上一篇我们了解了开发一个Controller的4种方法,如果不记得的朋友可以看看上一篇博文,今天我们来继续了解SpringMVC的模型与视图ModelAndView. 一.什么是Model? Mode ...
- kodexplorer免费网盘安装教程
KodExplorer是什么? KodExplorer可道云,原名芒果云,是基于Web技术的私有云和在线文件管理系统. 用户只需通过简单环境搭建,即可使用KodExplorer快速完成私有云/私有网盘 ...
- [LeetCode] Minimum Cost to Merge Stones 混合石子的最小花费
There are N piles of stones arranged in a row. The i-th pile has stones[i] stones. A move consists ...
- VUE 出现Access to XMLHttpRequest at 'http://192.168.88.228/login/Login?phone=19939306484&password=111' from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 'Access-Contr
报错如上图!!!! 解决办法首先打开 config -> index.js ,粘贴 如下图代码,'https://www.baidu.com'换成要访问的的api域名,注意只要域名就够了, ...
- hibernate的session的增删查改
一.增 //******************增加****************** Customer c = new Customer(); c.setCust_name("阿里云&q ...