当前位置: 首页 > news >正文

C# DotNetCore AOP简单实现

背景

实际开发中业务和日志尽量不要相互干扰嵌套,否则很难维护和调试。

示例

using System.Reflection;namespace CSharpLearn
{internal class Program{static void Main(){int age = 25;string name = "bingling";Person person = new(age, name);Console.WriteLine("====================不使用AOP====================");person.DisplayMessage();Console.WriteLine();person.DisplayMessage("name");Console.WriteLine("====================不使用AOP====================");Console.WriteLine();/*============================代理对象============================*/PersonProxyDynamic<Person> personProxyDynamic = new();personProxyDynamic.Before += (methodInfo) =>{List<string> pt = new();foreach (ParameterInfo? parameterInfo in methodInfo.GetParameters()){if (parameterInfo.ParameterType.FullName != null){pt.Add(parameterInfo.ParameterType.FullName);}}Console.WriteLine($"准备执行{methodInfo.Name}({string.Join(",", pt)})");};personProxyDynamic.After += (methodInfo) =>{Console.WriteLine($"执行{methodInfo.Name}完毕");};/*============================代理对象============================*/Console.WriteLine("====================使用了AOP====================");personProxyDynamic.Excute(person, "DisplayMessage", new object[] { "name" });Console.WriteLine();personProxyDynamic.Excute(person, "DisplayMessage", null);Console.WriteLine();personProxyDynamic.Excute(person, "DisplayMessage", new object[] { 123 });Console.WriteLine();Console.WriteLine("====================使用了AOP====================");}}/// <summary>/// 人物类/// </summary>public class Person{/// <summary>/// 姓名/// </summary>private readonly string name;/// <summary>/// 年龄/// </summary>private readonly int age;public Person(int age, string name){this.age = age;this.name = name;}/// <summary>/// 打印姓名和年龄/// </summary>public void DisplayMessage(){Console.WriteLine($"{{'age':{age},'name':'{name}'}}");}/// <summary>/// 根据需要打印姓名或年龄/// </summary>/// <param name="type">传入name或age</param>public void DisplayMessage(string type){switch (type){case "name":Console.WriteLine($"{{'name':'{name}'}}");break;case "age":Console.WriteLine($"{{'age':'{age}'}}");break;}}}/// <summary>/// 代理类/// </summary>/// <typeparam name="T">泛型T</typeparam>public class PersonProxyDynamic<T>{/// <summary>/// 执行方法前/// </summary>public Action<MethodInfo>? Before { get; set; }/// <summary>/// 执行方法后/// </summary>public Action<MethodInfo>? After { set; get; }/// <summary>/// 代理执行某个对象的某个方法/// </summary>/// <param name="t">被代理的对象</param>/// <param name="method">被执行的方法</param>/// <param name="args">被执行方法的参数列表</param>public void Excute(T t, string method, params object[]? args){//获取被代理对象的所有名字为传入method的方法MethodInfo[]? methodInfos = typeof(T).GetMethods().Where(item => item.Name == method).ToArray();//没有此名字的方法if (methodInfos == null || methodInfos.Length == 0 || methodInfos.FirstOrDefault(item => item == null) != null){Console.WriteLine($"{t}对象没有{method}方法");return;}//存在此名字的方法,注意区分是否为重载的方法foreach (MethodInfo methodInfo in methodInfos){//方法传参列表是否和args每个元素的类型一一对应bool flag = true;//无参方法,传入null或长度为0的参数列表都可以if (methodInfo.GetParameters().Length == 0 && (args == null || args.Length == 0)){}//有参方法,两者传参长度需要一致、且传入的参数类型等于方法的参数类型或者隶属于其子类else if (methodInfo.GetParameters().Length == args?.Length){for (int i = 0; i < methodInfo.GetParameters().Length; i++){Type type1 = methodInfo.GetParameters()[i].ParameterType;Type type2 = args[i].GetType();//参数列表类型不一致,且传入的参数类型不隶属于签名的参数类型if (type1 != type2 && !type2.IsSubclassOf(type1)){flag = false;break;}}}//有参方法,长度不一致else{flag = false;}//命中用户想调用的方法if (flag){Before?.Invoke(methodInfo);methodInfo.Invoke(t, args);After?.Invoke(methodInfo);return;}}Console.WriteLine("未找到您要调用的方法");}}
}

 运行结果

解析

业务中有一个Person类,其业务为调用Person实例的DisplayMessage方法打印该person对象的个人信息。

PersonProxyDynamic类为其动态代理类,我们在给其对象添加前置后置处理函数后,即可对person对象的所有方法进行代理,这样我们就可以在原本使用person对象方法的地方,替换成动态代理类的Execute方法,保证的原有的person代码不变,业务逻辑干净纯粹。

此示例仅供参考,由于使用了反射,生产环境若是对性能具备高要求,切勿轻易使用!!!

相关文章:

C# DotNetCore AOP简单实现

背景 实际开发中业务和日志尽量不要相互干扰嵌套&#xff0c;否则很难维护和调试。 示例 using System.Reflection;namespace CSharpLearn {internal class Program{static void Main(){int age 25;string name "bingling";Person person new(age, name);Conso…...

19.Tomcat搭建

Tomcat 简介 Tomcat的安装和启动 前置条件 • JDK 已安装(JAVA_HOME环境变量已被成功配置) Windows 下安装 访问 http://tomcat.apache.org ⇒ 左侧边栏 “Download” 2. 解压缩下载的文件到 “D:\tomcat”, tomcat的内容最终被解压到 “D:\tomcat\apache-tomcat-9.0.84” 3.…...

HarmonyOS云开发基础认证考试满分答案(100分)【全网最全-不断更新】【鸿蒙专栏-29】

系列文章&#xff1a; HarmonyOS应用开发者基础认证满分答案&#xff08;100分&#xff09; HarmonyOS应用开发者基础认证【闯关习题 满分答案】 HarmonyOS应用开发者高级认证满分答案&#xff08;100分&#xff09; HarmonyOS云开发基础认证满分答案&#xff08;100分&#xf…...

Unity项目里Log系统该怎么设计

其实并没有想完整就设计一个好用的Log系统&#xff0c;然后发出来。记录这个的原因&#xff0c;是在书里看到这么一句话&#xff0c;Log会消耗资源&#xff0c;特别是写文件&#xff0c;因此可以设置一个Log缓冲区&#xff0c;等缓冲区满了再一次性写入文件&#xff0c;以节省资…...

设计模式-状态(State)模式

目录 开发过程中的一些场景 状态模式的简单介绍 状态模式UML类图 类图讲解 适用场景 Java中的例子 案例讲解 什么是状态机 如何实现状态机 SpringBoot状态自动机 优点 缺点 与其他模式的区别 小结 开发过程中的一些场景 我们在平时的开发过程中&#xff0c;经常会…...

oracle怎么存放json好

Oracle数据库提供了多种方式来存储JSON数据。你可以将JSON数据存储在VARCHAR2、CLOB或BLOB数据类型中&#xff0c;或者使用Oracle提供的JSON数据类型。 如果你选择使用VARCHAR2数据类型来存储JSON数据&#xff0c;你可以直接将JSON字符串存储在其中。例如&#xff1a; CREATE…...

【计算机网络】—— 详解码元,传输速率的计算|网络奇缘系列|计算机网络

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 一见倾心,再见倾城 --- 计算机网络~&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 码元 速率和波特 思考1 思考2 思考3 带宽&#xff08;Bandwidth&#xff09; &#x1f4dd;总结 码元…...

[ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证

文章目录 一、前言二、在 Azure Portal 中创建 VM三、验证已创建的虚拟机资源3.1 方法一&#xff1a;在虚拟机服务中查看验证3.1 方法二&#xff1a;在资源组服务中查看验证 四、文末总结 一、前言 本文会开始创建新系列的专栏&#xff0c;专门更新 Azure 云实践相关的文章。 …...

计算机网络:网络层(无分类编址CIDR、计算题讲解)

带你快速通关期末 文章目录 前言一、无分类编址CIDR简介二、构成超网三、最长前缀匹配总结 前言 我们在前面知道了分类地址&#xff0c;但是分类地址又有很多缺陷&#xff1a; B类地址很快将分配完毕!路由表中的项目急剧增长! 一、无分类编址CIDR简介 无分类域间路由选择CI…...

Learning Semantic-Aware Knowledge Guidance forLow-Light Image Enhancement

微光图像增强&#xff08;LLIE&#xff09;研究如何提高照明并生成正常光图像。现有的大多数方法都是通过全局和统一的方式来改善低光图像&#xff0c;而不考虑不同区域的语义信息。如果没有语义先验&#xff0c;网络可能很容易偏离区域的原始颜色。为了解决这个问题&#xff0…...

关于嵌入式开发的一些信息汇总:开发模型以及自托管开发(二)

关于嵌入式开发的一些信息汇总&#xff1a;开发模型及自托管开发&#xff08;二&#xff09; 2 自托管开发2.2 构建 Raspberry Pi 内核2.3 安装内核2.4 总结 3 连接目标板3.1 Raspberry Pi 上的网络设置3.2 Ssh、rsh、rlogin 和 telnet 连接到目标 4 应用程序开发4.1 在目标板上…...

【JavaEE】多线程案例 - 定时器

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…...

网络小测------

使用软件PT7.0按照上面的拓扑结构建立网络&#xff0c;进行合理配置&#xff0c;使得所有计算机之间能够互相通信。并且修改各交换机的系统名称为&#xff1a;学号_编号&#xff0c;如你的学号为123&#xff0c;交换机Switch0的编号为0&#xff0c;则系统名称为123_0&#xff1…...

基于linux系统的Tomcat+Mysql+Jdk环境搭建(二)jdk1.8 linux 上传到MobaXterm 工具的已有session里

【JDK安装】 1.首先下载一个JDK版本 官网地址&#xff1a;http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载1.8版本&#xff0c;用红框标注出来了&#xff1a; 也许有的同学看到没有1.8版本&#xff0c;你可以随便下载一个linux的…...

04-Nacos中负载均衡规则的配置

负载均衡规则 同集群优先 默认的ZoneAvoidanceRule实现并不能根据同集群优先的规则来实现负载均衡,Nacos中提供了一个实现叫NacosRule可以优先从同集群中挑选服务实例 当服务消费者在本地集群找不到服务提供者时也会去其他集群中寻找,但此时会在服务消费者的控制台报警告 第…...

Kotlin 中的 `use` 关键字:优化资源管理(避免忘记inputStream.close() ?)

在 Android开发中&#xff0c;正确且高效地管理资源是至关重要的。use 关键字在 Kotlin 中为资源管理提供了一个简洁且强大的解决方案。它主要用于自动管理那些需要关闭的资源&#xff0c;比如文件、网络连接等。 一、use 关键字的工作原理 &#x1f916; use 是一个扩展函数…...

时序预测 | Python实现GRU-XGBoost组合模型电力需求预测

时序预测 | Python实现GRU-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现GRU-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前…...

扁平化菜单功能制作

网页效果&#xff1a; HTML部分&#xff1a; <body><ul class"nav"><li><a href"javascript:void(0);">菜单项目一</a><ul><li>子菜单项01</li><li>子菜单项02</li><li>子菜单项03<…...

网络基础——路由协议及ensp操作

目录 一、路由器及路由表 1.路由协议&#xff1a; 2.路由器转发原理&#xff1a; 3.路由表&#xff1a; 二、静态路由优缺点及特殊静态路由默认路由 1.静态路由的优缺点&#xff1a; 2.下一跳地址 3.默认路由 三、静态路由配置 四、补充备胎 平均负载 五、补充&…...

Python-折线图可视化

折线图可视化 1.JSON数据格式2.pyecharts模块介绍3.pyecharts快速入门4.创建折线图 1.JSON数据格式 1.1什么是JSON JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据JSON本质上是一个带有特定格式的字符串 1.2主要功能json就是一种在各个编程语言中流…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

python可视化:俄乌战争时间线关键节点与深层原因

俄乌战争时间线可视化分析&#xff1a;关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一&#xff0c;自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具&#xff0c;系统分析这场战争的时间线、关键节点及其背后的深层原因&#xff0c;全面…...