一看标题肯定会联想到使用动态编织的方式实现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. uva-10245-分治

    题意:数组二维空间内的点,求最近的俩个点的距离. 根据x排序,求左部分的最近距离,右部分最近距离,然后以中点,当前距离为半径,计算所有的点距离. #include <string> #in ...

  2. 学习笔记:FIS3

    http://fis.baidu.com/ FIS3官网 [配环境]: 1.先要安装node.js https://nodejs.org/en/ NODE.js官网(下载这个,下载后运行:  http ...

  3. ABAP-FTP-配置

    1.FTP配置: 设置FTP参数:IP地址.账号.密码.路径.RFC目标. 设置数据表:数据表及字段明细,设置查询字段及报表输出字段. 2.操作界面 3.程序 ZFID0003_ETL_FTP 主程序 ...

  4. 编织织物的knit course direction and knit wale direction

    来自:http://www.definetextile.com/2013/04/course-wale.html

  5. Dubbo+zookeeper面试题补充

    什么是分布式?什么是集群?主要区别 分布式是将一个服务分个部分,然后通过远程调用方式进行.远程调用框架RPC框架,spring cloud,dubbo.集群是将同一个服务的多个副本部署在不同的集群上, ...

  6. html常用代码合集

    <!>字体效果 <h1>...</h1>标题字(最大) <h6>...</h6>标题字(最小) <b>...</b> ...

  7. C++11 constexpr常量表达式

    常量表达式函数 要求: 函数体内只有单一的return返回语句 例如: constexpr int data() { const int i=1; //含有除了return以外的语句 return i ...

  8. 第一章 C++语言入门

            标准数据类型         C++语言提供了丰富的数据类型,如整数类型.实数类型(浮点数).字符类型等.每种数据类型均有均值范围,Dev-C++(4.9.9.2)是Windows平台 ...

  9. 业务数据实体(model) 需要克隆的方法

    业务数据实体(model) 需要克隆的时候 可以使用 Json.Deserialize<InquireResult>(Json.Serialize<InquireResult> ...

  10. 牛客小白月赛12 J 月月查华华的手机(序列自动机)

    ---恢复内容开始--- 题目来源:https://ac.nowcoder.com/acm/contest/392/J 题意: 题目描述 月月和华华一起去吃饭了.期间华华有事出去了一会儿,没有带手机. ...