首页 » 网站推广 » aopphpdll技巧_NET集成DeveloperSharp实现AOP经典扩充

aopphpdll技巧_NET集成DeveloperSharp实现AOP经典扩充

访客 2024-11-23 0

扫一扫用手机浏览

文章目录 [+]

1.第一个AOP程序

2.Aspect横切面编程

aopphpdll技巧_NET集成DeveloperSharp实现AOP经典扩充

3.一个横切面程序拦截多个主程序

aopphpdll技巧_NET集成DeveloperSharp实现AOP经典扩充
(图片来自网络侵删)

4.多个横切面程序拦截一个主程序

5.AOP的泛型处理(扩充)

6.AOP的异步处理(扩充)

7.上风总结

8.展望

0.序言AOP(Aspect Oriented Programming)是“面向横切面编程”,紧张是用来对程序/模块进行解耦。
怎么理解??

我们可以把一样平常的编程理解为“纵向编程”(主程序),比如如下的一个示例代码:

public string GetInfo(int i) { string s = \"大众\公众; if (i == 1) s = \"大众A\"大众; else if (i == 2) s = \"大众B\"大众; else if (i == 3) s = \"大众C\公众; else s = \"大众Z\"大众; return s; }

试想一下,上述软件实际利用后,

如果条件变量i有更多的判断值,我们是不是要在GetInfo()方法内部修正代码+重新编译?

如果后续须要加个日志记录功能,我们是不是也要在GetInfo()方法内部加上日志函数+重新编译?

如果...

更多如果...

为了避免上述的这些麻烦并增加软件的灵巧性,“横向编程”,也便是AOP被创造了出来,它就像是“横切一刀”,把干系功能塞进了主程序。

现行AOP的实现,紧张是通过拦截方法(即拦截主程序),并修正其参数+返回值来完成。

网上有很多干系方案,比如:特性注释拦截、动态代码天生、叮嘱消磨代理模式、等。
但这些方案要么实现的很繁芜、要么耦合度没完备割断、逻辑有变革时还是须要修正代码重新编译。
均不足空想。

而本日要隆重登场的主角-DeveloperSharp平台中的AOP技能,则供应了一种简便、快捷、彻底解耦的AOP实现。
利用它,在程序逻辑有变革时,你只须要修正配置文件就行,而不再须要对主程序进行一丁丁点的代码修正!

(若碰着问题,须要技能支持??请添加微信:894988403)

1.第一个AOP程序

制作一个AOP程序须要四个步骤:

(1)制作主程序

(2)制作横切面程序

(3)制作配置文件,让横切面程序拦截主程序

(4)调用主程序

下面,我们一步一步来实现上述四个步骤。

【第一步】:制作主程序

我们在Visual Studio中新建一个名为“School.Logic”的类库工程,并在该工程中新建一个名为PersonManage的类,该类中有一个名为GetInfo1的方法,代码如下:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model;namespace School.Logic{ //主程序必须继续自LogicLayer类 public class PersonManage : LogicLayer { public string GetInfo1(string Name, int Num) { return $\"大众共有{Name}{Num}人\"大众; } }}

以上,编写了一个非常大略的主程序。

【第二步】:制作横切面程序

我们再在Visual Studio中新建一个名为“School.Aspect”的类库工程,并在该工程中新建一个名为Interceptor1的类,代码如下:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model.Aspect;namespace School.Aspect{ //横切面程序必须继续自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序实行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = \"大众老师\"大众; e.MethodInfo.ParameterValues[1] = 20; } //PostProcess方法后于主程序实行 public override void PostProcess(object sender, AspectEventArgs e) { } }}

以上,编写了一个横切面程序。
它的紧张功能是把主程序方法的两个参数值给改掉。
AspectModel基类中的PreProcess方法会在主程序方法实行之前被实行,而PostProcess方法会在主程序方法实行之后被实行。
它两便是AOP横向拦截的核心要素。
它两均须要被override重写覆盖掉。

【第三步】:制作配置文件,让横切面程序拦截主程序

若是在.Net Core环境下,我们创建一个名为DeveloperSharp.json的配置文件,设置让Interceptor1拦截PersonManage中的GetInfo1方法。
文件内容如下:

{ \"大众DeveloperSharp\"大众: { \"大众AspectObject\"大众: [ { \"大众name\公众:\"大众School.Aspect.Interceptor1\公众, //横切面拦截器类 \公众scope\"大众:\公众School.Logic.PersonManage\"大众, //被拦截的主程序类 \"大众method\公众:\公众GetInfo1\"大众 //被拦截的方法 } ] }}

若是在.Net Framework环境下,我们创建一个名为DeveloperSharp.xml的配置文件,设置让Interceptor1拦截PersonManage中的GetInfo1方法。
文件内容如下:

<?xml version=\"大众1.0\"大众 encoding=\"大众utf-8\公众 ?><DeveloperSharp> <AspectObject> <Ao name=\"大众School.Aspect.Interceptor1\"大众 scope=\"大众School.Logic.PersonManage\"大众 method=\"大众GetInfo1\公众/> </AspectObject></DeveloperSharp>

把稳:以上配置中所有的类名,都要用完备限定名。

【第四步】:调用主程序

末了,我们再在Visual Studio中创建一个掌握台工程,让它来调用主程序中的GetInfo1方法,代码如下:

//须要引用School.Aspect、School.Logic、DeveloperSharp三项 static void Main(string[] args) { var pm = new School.Logic.PersonManage(); //要用这种形式调用主程序中的方法,AOP功能才会生效 var str = pm.InvokeMethod(\"大众GetInfo1\"大众, \"大众学生\"大众, 200); Console.WriteLine(str); Console.ReadLine(); }

附注:有人会以为上述InvokeMethod这种调用方法不足优雅,但事实上ASP.NET Web Api也是被类似InvokeMethod这种办法包裹调用才实现了各种Filter拦截器的拦截(实质也是AOP),只不过它的这个InvokeMethod动作是在.NET自身的CLR管道运行时中进行的。
而且,那些Filter拦截器还只能用于ASP.NET Web Api环境,而不能像本方案这样用于一样平常程序。

现在,为了让前面第三步创建的配置文件生效,我们此时还须要在此主调项目中对它进行链接:

若是在.Net Core环境下,我们只须要把DeveloperSharp.json文件放到程序实行目录中(即bin目录下与dll、exe等文件的同一目录中,放错了位置会报错)(把稳:有些.Net Core版本在Visual Studio“调试”时,不会在bin目录下天生全部的dll、exe,此时须要把此配置文件放在运用程序的“根目录”下)。
若是在.Net Framework环境下,我们须要在工程配置文件App.config/Web.config中添加appSettings节点,节点内容如下:

<appSettings> <add key=\公众ConfigFile\"大众 value=\公众D:\Test\Assist\DeveloperSharp.xml\"大众 /> </appSettings>

此处须要设置为配置文件的“绝对路径”(利用“绝对路径”而不是“相对路径”,一是有利于安全性,二是有利于分布式支配)

统统准备完毕,运行,结果如下:

【掌握台显示出】:共有老师20人

可见AOP已经拦截成功。

若此时,我们在配置文件DeveloperSharp.json/DeveloperSharp.xml中稍做修正,比如:把“GetInfo1”这个方法名改为“ABC”这样一个不存在的方法名,再运行,结果如下:

【掌握台显示出】:共有学生200人

2.Aspect横切面编程

上面,第二步,制作的横切面程序,是通过修正主程序方法的参数值,而终极改变了主程序的返回值。

实在,我们也有办法直接修正主程序方法的返回值,比如把上面Interceptor1类的代码修正为如下:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model.Aspect;namespace School.Aspect{ //横切面程序必须继续自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序实行 public override void PreProcess(object sender, AspectEventArgs e) { } //PostProcess方法后于主程序实行 public override void PostProcess(object sender, AspectEventArgs e) { //把主程序的返回值改掉 e.MethodInfo.ReturnValue = $\"大众共有校长2人\公众; } }}

运行,结果如下:

【掌握台显示出】:共有校长2人

到目前为止,我们已经知道了如何通过“Aspect横切面程序”修正主程序方法的参数值、返回值。

如果我们想进一步获取主程序的“命名空间”、“类名”、“方法名”、“参数名”、“参数类型”、“返回值类型”,则可以通过如下代码获取:

e.MethodInfo.NamespaceName //命名空间e.MethodInfo.ClassName //类名e.MethodInfo.MethodName //方法名e.MethodInfo.ParameterInfos[0].Name //参数名(第一个参数)e.MethodInfo.ParameterInfos[0].ParameterType //参数类型(第一个参数)e.MethodInfo.ReturnValue.GetType() //返回值类型

有时候,在某些分外情形下,我们希望主程序方法不运行,此时则可以通过在PreProcess方法里把e.Continue设置为false来完成。

接前面的“第一个AOP程序”,比如:我们希望当人数大于10000时,主程序方法就不再运行,则可以通过把Interceptor1类的代码修正为如下样式来实现:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model.Aspect;namespace School.Aspect{ //横切面程序必须继续自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序实行 public override void PreProcess(object sender, AspectEventArgs e) { //当人数大于10000时,主程序方法就不再运行 if (Convert.ToInt32(e.MethodInfo.ParameterValues[1]) > 10000) e.Continue = false; } //PostProcess方法后于主程序实行 public override void PostProcess(object sender, AspectEventArgs e) { } }}

现在的这个示例是一个Aspect横切面程序拦截一个主程序。
在后续将要讲解的“多个Aspect横切面程序拦截一个主程序”的情形中,只要有一个e.Continue=false被设置,主程序方法就不会运行(在此事先提点)。

3.一个横切面程序拦截多个主程序

为了演示这部分的内容,我们首先在前面“第一个AOP程序”的根本上,把主程序进行扩充。
采纳的动作是:

(1)在PersonManage类中增加一个GetInfo2方法

(2)再新增一个主程序类SystemManage,该类中有一个名为GetMessage1的方法。
代码如下:

PersonManage类:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model;namespace School.Logic{ //主程序必须继续自LogicLayer类 public class PersonManage : LogicLayer { public string GetInfo1(string Name, int Num) { return $\"大众共有{Name}{Num}人\"大众; } public string GetInfo2(string Name, int Num) { return $\公众学校共有{Name}{Num}人\公众; } }}

SystemManage类:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model;namespace School.Logic{ //主程序必须继续自LogicLayer类 public class SystemManage : LogicLayer { public string GetMessage1(string Name1, int Num1, string Name2, int Num2) { return $\"大众第一组共有{Name1}{Num1}人,第二组共有{Name2}{Num2}人\公众; } }}

如此一来,现在就有了3个主程序方法。

接下来,我们修正配置文件,让Interceptor1去拦截上述的3个主程序方法。

若是在.Net Core环境下,DeveloperSharp.json文件的内容修正为如下:

{ \公众DeveloperSharp\公众: { \"大众AspectObject\"大众: [ { \公众name\"大众:\"大众School.Aspect.Interceptor1\公众, \"大众scope\"大众:\"大众School.Logic.PersonManage\"大众, \"大众method\"大众:\"大众\公众 //星号代表该浸染域下的全部方法 }, { \"大众name\公众:\"大众School.Aspect.Interceptor1\公众, \公众scope\"大众:\"大众School.Logic.SystemManage\"大众, \"大众method\"大众:\"大众GetMessage1\"大众 } ] }}

若是在.Net Framework环境下,DeveloperSharp.xml文件的内容修正为如下:

<?xml version=\"大众1.0\"大众 encoding=\公众utf-8\公众 ?><DeveloperSharp> <AspectObject> <Ao name=\公众School.Aspect.Interceptor1\"大众 scope=\公众School.Logic.PersonManage\公众 method=\公众\"大众/> <Ao name=\"大众School.Aspect.Interceptor1\"大众 scope=\"大众School.Logic.SystemManage\公众 method=\"大众GetMessage1\"大众/> </AspectObject></DeveloperSharp>

末了,我们把掌握台启动程序修正为如下:

//须要引用School.Aspect、School.Logic、DeveloperSharp三项 static void Main(string[] args) { var pm = new School.Logic.PersonManage(); var sm = new School.Logic.SystemManage(); //要用这种形式调用主程序中的方法,AOP功能才会生效 var str1 = pm.InvokeMethod(\"大众GetInfo1\公众, \"大众学生\公众, 200); var str2 = pm.InvokeMethod(\公众GetInfo2\公众, \公众学生\"大众, 200); var str3 = sm.InvokeMethod(\"大众GetMessage1\"大众, \公众学生\"大众, 200, \"大众院士\"大众, 10); Console.WriteLine(str1); Console.WriteLine(str2); Console.WriteLine(str3); Console.ReadLine(); }

运行结果如下:

【掌握台显示出】:

共有老师20人学校共有老师20人第一组共有老师20人,第二组共有院士10人

可见AOP所有拦截均已成功!

4.多个横切面程序拦截一个主程序

为了演示这部分的内容,我们还是要先回到前面的“第一个AOP程序”,在它的根本上,我们新增一个名为Interceptor2的Aspect横切面类,代码如下:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model.Aspect;namespace School.Aspect{ //横切面程序必须继续自AspectModel类 public class Interceptor2 : AspectModel { //PreProcess方法先于主程序实行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = \"大众辅导员\公众; e.MethodInfo.ParameterValues[1] = 40; } //PostProcess方法后于主程序实行 public override void PostProcess(object sender, AspectEventArgs e) { } }}

如此一来,我们就有了2个Aspect横切面程序Interceptor1与Interceptor2。

接下来,我们修正配置文件,让Interceptor1、Interceptor2都去拦截主程序方法GetInfo1。

若是在.Net Core环境下,DeveloperSharp.json文件的内容修正为如下:

{ \"大众DeveloperSharp\"大众: { \公众AspectObject\"大众: [ { \"大众name\"大众:\"大众School.Aspect.Interceptor1\"大众, \"大众scope\公众:\"大众School.Logic.PersonManage\"大众, \公众method\"大众:\"大众GetInfo1\"大众 }, { \公众name\"大众:\"大众School.Aspect.Interceptor2\"大众, \公众scope\"大众:\"大众School.Logic.PersonManage\"大众, \公众method\"大众:\"大众GetInfo1\"大众 } ] }}

若是在.Net Framework环境下,DeveloperSharp.xml文件的内容修正为如下:

<?xml version=\"大众1.0\公众 encoding=\"大众utf-8\"大众 ?><DeveloperSharp> <AspectObject> <Ao name=\"大众School.Aspect.Interceptor1\"大众 scope=\"大众School.Logic.PersonManage\"大众 method=\"大众GetInfo1\公众/> <Ao name=\公众School.Aspect.Interceptor2\公众 scope=\公众School.Logic.PersonManage\公众 method=\"大众GetInfo1\"大众/> </AspectObject></DeveloperSharp>

上述修正完毕,运行掌握台主调程序,结果如下:

【掌握台显示出】:共有辅导员40人

从上述运行结果,我们大致可以推断出:Interceptor1、Interceptor2这两个Aspect横切面拦截器是按配置顺序实行的。
个中,Interceptor1先把GetInfo1方法的两个参数值改为了(\"大众老师\"大众,20),接着,Interceptor2又把GetInfo1方法的两个参数值改为了(\公众辅导员\公众,40),以是终极GetInfo1方法的参数值变为了(\公众辅导员\公众,40)。

5.AOP的泛型处理如果我们的主程序是泛型方法,则须要用InvokeMethod<T>这种办法来进行调用。
比如,现有如下的主程序代码:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model;namespace Test4Logic{ //主程序必须继续自LogicLayer类 public class Calculate : LogicLayer { public int add(int i, int j) { return i + j; } public int add(int i, int j, int k) { return i + j + k; } public string add<T>(T i, T j, T k) { return \"大众T\"大众 + i.ToString() + j.ToString() + k.ToString(); } public string add<T, V>(T i, T j, V k) { return \"大众TTV\"大众 + i.ToString() + j.ToString() + k.ToString(); } public string add<T, V>(T i, V j, V k) { return \公众TVV\"大众 + i.ToString() + j.ToString() + k.ToString(); } }}

对应的Aspect横切面类代码如下:

//从NuGet引用DeveloperSharp包(须要是最新版)using DeveloperSharp.Structure.Model.Aspect;namespace Test4Aspect{ //横切面程序必须继续自AspectModel类 public class Interceptor : AspectModel { //PreProcess方法先于主程序实行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的第一个参数值改掉 e.MethodInfo.ParameterValues[0] = 8; } //PostProcess方法后于主程序实行 public override void PostProcess(object sender, AspectEventArgs e) { } }}

对应的配置文件如下:若是在.Net Core环境下,DeveloperSharp.json文件的内容如下:

{ \"大众DeveloperSharp\公众: { \"大众AspectObject\公众: [ { \"大众name\"大众:\"大众Test4Aspect.Interceptor\"大众, //横切面拦截器类 \公众scope\"大众:\"大众Test4Logic.Calculate\"大众, //被拦截的主程序类 \"大众method\公众:\"大众add\"大众 //被拦截的方法 } ] }}

若是在.Net Framework环境下,DeveloperSharp.xml文件的内容如下:

<?xml version=\"大众1.0\"大众 encoding=\"大众utf-8\公众 ?><DeveloperSharp> <AspectObject> <Ao name=\"大众Test4Aspect.Interceptor\"大众 scope=\"大众Test4Logic.Calculate\"大众 method=\"大众add\"大众/> </AspectObject></DeveloperSharp>

掌握台主调程序代码如下:

//须要引用Test4Aspect、Test4Logic、DeveloperSharp三项 static void Main(string[] args) { var cal = new Test4Logic.Calculate(); //要用这种形式调用主程序中的方法,AOP功能才会生效 var r1 = cal.InvokeMethod(\"大众add\"大众, 1, 2); var r2 = cal.InvokeMethod(\公众add\"大众, 1, 2, 3); var r3 = cal.InvokeMethod<int>(\公众add\"大众, 1, 2, 3); var r4 = cal.InvokeMethod<int, float>(\公众add\"大众, 1, 2, (float)3); var r5 = cal.InvokeMethod<int, float>(\"大众add\公众, 1, (float)2, (float)3); Console.WriteLine(r1); Console.WriteLine(r2); Console.WriteLine(r3); Console.WriteLine(r4); Console.WriteLine(r5); Console.ReadLine(); }

运行上述掌握台主调程序,结果如下:

【掌握台显示出】:1013T823TTV823TVV823

主程序中每个泛型方法的对应调用一览无余。

6.AOP的异步处理如果我们的主程序是异步方法,还是利用InvokeMethod来进行调用。
下面给出一个代码样式示例(代码做了简化处理):

//主程序 //主程序必须继续自LogicLayer类 public class UserService : LogicLayer { public async Task<Worker> GetUser(string Id, int Age, string Name) { //...干系代码... } public async Task<T> GetUser<T>(string Id, int Age, string Name) where T : User, new() { //...干系代码... } }----------------------------------------------------------------------//主调程序 var us = new UserService(); //要用这种形式调用主程序中的方法,AOP功能才会生效 var worker = await us.InvokeMethod(\"大众GetUser\"大众, \"大众C007\公众, 26, \"大众alex\公众); var user = await us.InvokeMethod<Manager>(\"大众GetUser\"大众, \公众A002\公众, 46, \"大众kevin\"大众); Console.WriteLine(worker.Name); Console.WriteLine(user?.Name);

即然主程序可以是异步的,那Aspect横截面拦截程序能不能也是异步的了?答案是肯定的。
你可以把PreProcess与PostProcess中的至少一个改为异步方法,实现单个Aspect类的同步异步混用,其代码构造与原来的同步Aspect类同等,这点连.NET/微软自身都还没有实现...下面给出一个示例代码:

//横切面程序必须继续自AspectModel类 public class UserInterceptor : AspectModel { //PreProcess方法先于主程序实行 public override void PreProcess(object sender, AspectEventArgs e) { } //PostProcess方法后于主程序实行 public override async void PostProcess(object sender, AspectEventArgs e) { await Task.Run(() => { Thread.Sleep(10000); File.AppendAllText(\"大众D:/zzz.txt\"大众, \"大众耗时操作\公众); }); } }

7.上风总结

本文所讲述的,是全网唯一实现AOP彻底解耦的技能方案。
利用它,当你须要给主程序增加Aspect横切面拦截器时,无论是增加一个还是多个,都不再须要修正&重新编译主程序。
这实现了不同功能构件之间的0依赖拼装/拆卸开拓办法,随之而来的也会对研发团队的管理模式产生重大影响,意义深远...

8.展望

AOP对付程序代码的解耦、业务模块的拆分与拼装组合,有着巨大的浸染。
精确的利用AOP,乃至能对传统的软件架构设计,产生颠覆性的影响,如超级战士出场一样平常,让所有人刮目相看,完备线人一新!

为了让读者能直不雅观感知AOP的上述神奇魅力,下面给出一个业务案例:有一批货品要录入数据库,货品包含长、宽、高、颜色、类型等属性。
现在有业务需求如下,(1)当货品长度大于10厘米时,它在数据库中标记为A类;当货品长度大于20厘米时,标记为B类。
(2)当货品颜色无法分辨时,统一在数据库中默认标记为白色。
(3)每个货品录入数据库后,还要在另一个财务数据库中录入该货品的价格信息,同时把该货品的操作员名字记入日志文件。

这样的一个业务案例,你以前会怎么设计这个程序?本日学了AOP后你又会怎么设计程序?你会创建几个Aspect横切面了...?

-End-

点击上方卡片关注"大众号,
回答'口试',获取C#/.NET/.NET Core口试宝典
回答'C#',领取零根本学习C#编程
回答'NET',领取.NET零根本入门到实战
回答'Linux',领取Linux从入门到精通
回答'wpf',领取高薪热门【WPF上位机+工业互联网】从零手写实战
回答'Modbus',领取初识C#+上位机Modbus通信
回答'PLC',领取C#措辞与西门子PLC的通信实操
回答'blazor',领取blazor从入门到实战
回答'TypeScript',领取前端热门TypeScript系统教程
回答'vue',领取vue前端从入门到精通
回答'23P',领取C#实现23种常见设计模式
回答'MongoDB',领取MongoDB实战
回答'Trans',领取分布式事务
回答'Lock',领取分布式锁实践
回答'Docker',领取微做事+Docker综合实战
回答'K8s',领取K8s支配微做事

回答'加群',进.NET技能社区互换群

相关文章

Python编程从入门到精通,探索编程之美

编程已经成为现代社会的一项基本技能。Python作为一种简单易学、功能强大的编程语言,在我国教育领域备受关注。本文将从Python...

网站推广 2025-03-02 阅读1 评论0

Scum07代码编程之美与适用方法

编程已成为当今社会不可或缺的技能之一。Scum07代码作为一款经典的编程语言,在我国众多程序员中备受推崇。本文将深入解析Scum0...

网站推广 2025-03-02 阅读1 评论0

Linux环境下的前端代码运行优化与步骤

前端技术逐渐成为软件开发的核心。Linux操作系统因其稳定性、安全性、开放性等特点,成为众多开发者和企业青睐的运行环境。本文将从L...

网站推广 2025-03-02 阅读1 评论0