1. 程式人生 > >在.NET Core中三種實現“可插拔”AOP編程方式(附源碼)

在.NET Core中三種實現“可插拔”AOP編程方式(附源碼)

必須 n) 即使 extension cti 開閉 void 定義 面向切面編程

原文:在.NET Core中三種實現“可插拔”AOP編程方式(附源碼)

一看標題肯定會聯想到使用動態編織的方式實現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}”功能。

1     public interface ISay
2     {
3         PeopleModel SayHello(PeopleModel peopleModel);
4     }
1     public class Say : ISay
2     {
3         public PeopleModel SayHello(PeopleModel peopleModel)
4         {
5             peopleModel.Name = $"hello {peopleModel.Name}";
6             return
peopleModel; 7 } 8 }
1     public class PeopleModel
2     {
3         public string Name { get; set; } = "";
4         public int Age { get; set; }
5         public int Sex { get; set; }
6     }

再創建一個MVC控制器

 1     [Route("api/[controller]")]
 2     [ApiController]
 3     public class DemoController : ControllerBase
 4     {
 5         [HttpGet]
 6         public PeopleModel Get([FromQuery] PeopleModel peopleModel)
 7         {
 8             return Say.SayHello(peopleModel);
 9         }
10     }

很簡單的,不做解釋,以免浪費篇幅。

DynamicProxy方式

動態代理的方式在JAVA上很早就出現了,比如在Spring框架裏面。而NET中利用Autofac和Castle這兩個框架同樣也可以實現動態代理。

需要用到的框架如下:

Autofac:提供容器控制
Autofac.Extensions.DependencyInjection:對autofac依賴註入進行擴展
Autofac.Extras.DynamicProxy:對autofac動態代理進行擴展
Castle.Core:使用動態代理的實現

相信autofac很多朋友都不陌生了,而配合Castle框架就能實現動態代理模式,我們新建一個攔截器類,名為InjectInterceptor,而且必須要實現IInterceptor(該接口在Castle.DynamicProxy中),完整代碼如下:

 1 using System;
 2 using Castle.DynamicProxy;
 3 
 4 namespace InterceptDemo.Intercepts.Inject
 5 {
 6     public class InjectInterceptor : IInterceptor
 7     {
 8         public virtual void Intercept(IInvocation invocation)
 9         {
10             PreProceed(invocation);
11             invocation.Proceed();
12             PostProceed(invocation);
13         }
14 
15         private void PreProceed(IInvocation invocation)
16         {
17             Console.WriteLine($"{DateTime.Now} inject interceptor invoke preproceed"); 
18         }
19 
20         private void PostProceed(IInvocation invocation)
21         {
22             Console.WriteLine($"{DateTime.Now} inject interceptor invoke postproceed");
23         }
24     }
25 }

當繼承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框架中,使用過濾器的地方非常非常的多,筆者不作一一介紹,直接貼代碼:

 1     public class ActionFilter : ActionFilterAttribute
 2     {
 3         public override void OnActionExecuting(ActionExecutingContext context)
 4         {
 5             Console.WriteLine($"{DateTime.Now} on action exceuting");
 6         }
 7 
 8         public override void OnActionExecuted(ActionExecutedContext context)
 9         {
10             Console.WriteLine($"{DateTime.Now} on action exceuted");
11         }
12     }

Middleware方式

中間件不僅可以實現自定義管道,還也可以作為netcore invoke的AOP編程。我們先建立一個對ApplicationBuilder的擴展類

1     public static class InterceptHandler
2     {
3         public static IApplicationBuilder UseInterceptMiddleware(this IApplicationBuilder app)
4         {
5             return app.UseMiddleware<InterceptMiddlware>();
6         }
7     }

再建立一個中間件

 1 using System;
 2 using System.Threading.Tasks;
 3 using Microsoft.AspNetCore.Http;
 4 
 5 namespace InterceptDemo.Intercepts.Middleware
 6 {
 7     public class InterceptMiddlware
 8     {
 9         private readonly RequestDelegate _next;
10         
11         public InterceptMiddlware(RequestDelegate next)
12         {
13             _next = next;
14         }
15 
16         public async Task Invoke(HttpContext context)
17         {
18             PreProceed(context);
19             await _next(context);
20             PostProceed(context);
21         }
22 
23         private void PreProceed(HttpContext context)
24         {
25             Console.WriteLine($"{DateTime.Now} middleware invoke preproceed");
26         }
27 
28         private void PostProceed(HttpContext context)
29         {
30             Console.WriteLine($"{DateTime.Now} middleware invoke postproceed");
31         }
32     }
33 }

運行結果如下

技術分享圖片

總結一下

在NETCORE中可以使用AOP的方式有很多很多,包括國內優秀的開源框架asp.netcore同樣可以實現AOP編程模式。

筆者所提供的三種AOP方式可適用如下

Filter:身份驗證,參數驗證,處理耗時等等WEB處理級的服務。

DynamicProxy:功能模塊之間的解耦和重用服務。

Middleware:Request和Response之間建立的通信等底層服務,必要時還可以實現自定義管道。

感謝閱讀!

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

在.NET Core中三種實現“可插拔”AOP編程方式(附源碼)