一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点。

本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),DynamicProxy(动态代理方式,JAVA上早已不是新鲜事),Middleware(netcore中间件所实现的AOP方式)

什么是AOP编程

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

换白话文就是:保证开闭原则的前提下,不修改某一个模块(或函数)的任何一行代码,从而实现对该模块的横向扩展。

可插拔:即使抛弃AOP,核心内容仍然可以运行,降低耦合,提高可重用。

创建一个“能说你好,某某某”的ASP .NET CORE WebApi项目

创建项目步骤此处略过,呵呵。

我们假定一个最简单的“Say Hello”作为项目需求,通过URL传递姓名,再返回“hello {name}”。因此创建一个简单模型PeopleModel,创建一个接口ISay,并用Say实现ISay中的“hello {name}”功能。

     public interface ISay
{
PeopleModel SayHello(PeopleModel peopleModel);
}
     public class Say : ISay
{
public PeopleModel SayHello(PeopleModel peopleModel)
{
peopleModel.Name = $"hello {peopleModel.Name}";
return peopleModel;
}
}
     public class PeopleModel
{
public string Name { get; set; } = "";
public int Age { get; set; }
public int Sex { get; set; }
}

再创建一个MVC控制器

     [Route("api/[controller]")]
[ApiController]
public class DemoController : ControllerBase
{
[HttpGet]
public PeopleModel Get([FromQuery] PeopleModel peopleModel)
{
return Say.SayHello(peopleModel);
}
}

很简单的,不做解释,以免浪费篇幅。

DynamicProxy方式

动态代理的方式在JAVA上很早就出现了,比如在Spring框架里面。而NET中利用Autofac和Castle这两个框架同样也可以实现动态代理。

需要用到的框架如下:

Autofac:提供容器控制
Autofac.Extensions.DependencyInjection:对autofac依赖注入进行扩展
Autofac.Extras.DynamicProxy:对autofac动态代理进行扩展
Castle.Core:使用动态代理的实现

相信autofac很多朋友都不陌生了,而配合Castle框架就能实现动态代理模式,我们新建一个拦截器类,名为InjectInterceptor,而且必须要实现IInterceptor(该接口在Castle.DynamicProxy中),完整代码如下:

 using System;
using Castle.DynamicProxy; namespace InterceptDemo.Intercepts.Inject
{
public class InjectInterceptor : IInterceptor
{
public virtual void Intercept(IInvocation invocation)
{
PreProceed(invocation);
invocation.Proceed();
PostProceed(invocation);
} private void PreProceed(IInvocation invocation)
{
Console.WriteLine($"{DateTime.Now} inject interceptor invoke preproceed");
} private void PostProceed(IInvocation invocation)
{
Console.WriteLine($"{DateTime.Now} inject interceptor invoke postproceed");
}
}
}

当继承IInterceptor接口时,必须要实现Intercept虚方法,该方法将传递IInvocation接口参数,调用Proceed函数将会实现方法体以外的函数,就是切面以外的函数。使用时只需要通过特性即可实现AOP方式,我们稍微修改一下Say这个类,增加一句话:[Intercept(typeof(InjectInterceptor))]

当然,还需要在autofac中实现注册才行,代码如下:

var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<Say>().As<ISay>().EnableInterfaceInterceptors();
builder.RegisterType<InjectInterceptor>();

Filter方式

过滤器的方式就更加简单了,在ASP.NET框架中,使用过滤器的地方非常非常的多,笔者不作一一介绍,直接贴代码:

     public class ActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine($"{DateTime.Now} on action exceuting");
} public override void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine($"{DateTime.Now} on action exceuted");
}
}

Middleware方式

中间件不仅可以实现自定义管道,还也可以作为netcore invoke的AOP编程。我们先建立一个对ApplicationBuilder的扩展类

     public static class InterceptHandler
{
public static IApplicationBuilder UseInterceptMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<InterceptMiddlware>();
}
}

再建立一个中间件

 using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; namespace InterceptDemo.Intercepts.Middleware
{
public class InterceptMiddlware
{
private readonly RequestDelegate _next; public InterceptMiddlware(RequestDelegate next)
{
_next = next;
} public async Task Invoke(HttpContext context)
{
PreProceed(context);
await _next(context);
PostProceed(context);
} private void PreProceed(HttpContext context)
{
Console.WriteLine($"{DateTime.Now} middleware invoke preproceed");
} private void PostProceed(HttpContext context)
{
Console.WriteLine($"{DateTime.Now} middleware invoke postproceed");
}
}
}

运行结果如下

总结一下

在NETCORE中可以使用AOP的方式有很多很多,包括国内优秀的开源框架asp.netcore同样可以实现AOP编程模式。

笔者所提供的三种AOP方式可适用如下

Filter:身份验证,参数验证,处理耗时等等WEB处理级的服务。

DynamicProxy:功能模块之间的解耦和重用服务。

Middleware:Request和Response之间建立的通信等底层服务,必要时还可以实现自定义管道。

感谢阅读!

源码地址:https://github.com/steveleeCN87/C-.three.aop.programming

在.NET Core中三种实现“可插拔”AOP编程方式(附源码)的更多相关文章

  1. 微信小程序中如何实现分页下拉加载?(附源码)

    转眼间坚持写教你微信小程序系列已经有十节系列课程了,每天的工作压力繁重,小女子也不知道自己还能坚持这样的系列教程多久.只希望每篇教程真的对大家有帮助.这节课我们要介绍的就是如何实现分页的下拉加载,我们 ...

  2. .NET Core 中三种模式依赖注入的生命周期。

    注入模式 同一个请求作用域 不同的请求作用域 AddSingleton 同一个实例 同一个实例 AddScoped 同一个实例 新实例 AddTransient 新实例 新实例

  3. EF Core 快速上手——EF Core的三种主要关系类型

    系列文章 EF Core 快速上手--EF Core 入门 本节导航 三种数据库关系类型建模 Migration方式创建和习修改数据库 定义和创建应用DbContext 将复杂查询拆分为子查询   本 ...

  4. iOS开发UI篇—iOS开发中三种简单的动画设置

    iOS开发UI篇—iOS开发中三种简单的动画设置 [在ios开发中,动画是廉价的] 一.首尾式动画 代码示例: // beginAnimations表示此后的代码要“参与到”动画中 [UIView b ...

  5. C#中三种定时器对象的比较

    ·关于C#中timer类 在C#里关于定时器类就有3个1.定义在System.Windows.Forms里2.定义在System.Threading.Timer类里3.定义在System.Timers ...

  6. 转-Web Service中三种发送接受协议SOAP、http get、http post

    原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...

  7. C#中三种定时器对象的比较 【转】

    https://www.cnblogs.com/zxtceq/p/5667281.html C#中三种定时器对象的比较 ·关于C#中timer类 在C#里关于定时器类就有3个1.定义在System.W ...

  8. Spring中三种配置Bean的方式

    Spring中三种配置Bean的方式分别是: 基于XML的配置方式 基于注解的配置方式 基于Java类的配置方式 一.基于XML的配置 这个很简单,所以如何使用就略掉. 二.基于注解的配置 Sprin ...

  9. 深入浅出spring IOC中三种依赖注入方式

    深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...

随机推荐

  1. Java编写串口程序

    用Java编写串口程序一般都会用到这个 http://fizzed.com/oss/rxtx-for-java 根据电脑的情况下载 解压以后有安装文档 For a JDK installation: ...

  2. linux shell并发执行命令

    一般我们在linux上十一shell命令的批量执行操作,一般使用for或者while 循环进行操作,但是这样有一个问题,for或者while本质上是串行的,并不能,如果某一个命令执行耗费的时间比较长, ...

  3. Mesh属性[Unity]

    Mesh属性[Unity] Mesh是Unity内的一个组件,称为网格组件.3D网格是Unity中最重要的图形元素.在Unity中存在多种组件用于渲染标准网格或者蒙皮网格.拖尾或者3D线条. 在Uni ...

  4. 微商城分享 包括app分享 微信分享

    <template> <div class="spr"> <img src="../../assets/images/activity/sh ...

  5. cdnbest日志分析显示404的原因

    日志分析报404原因 报这个提示一般是日志没有开启或还没有日志 检查下面几点: 开启和关闭站点日志在节点3311中显示如下图nolog是关闭  日志翻转目前默认是1个小时以后会默认改成20分钟,翻转时 ...

  6. DB2(Procedure)存储过程遍历循环!

    有时候一些复杂的业务逻辑将要通过存储过程的循环语句进行处理;以下列出2种DB2存储过程的循环语句,方便以后的查看并使用! 推荐第一种方式的使用,最大的优点就是比较直观;在需要操作很多字段的情况下,不需 ...

  7. 搭建React项目(一):在网页中使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. swift 监测内存泄漏 MLeaksFinder

    使用MLeaksFinder检测项目内存泄露总结 https://www.cnblogs.com/ocarol/p/5288497.html

  9. ES6 proxy(代理拦截) &&Reflect

  10. 现代编译原理--第六章(中间树 IR Tree 含源码)

    (转载请表明出处   http://www.cnblogs.com/BlackWalnut/p/4559717.html ) 这一章,就虎书而言,理论知识点是及其少的,就介绍了为什么要有一个中间表示树 ...