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代码不变,业务逻辑干净纯粹。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/282513.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio好用的插件推荐

目录 一、插件推荐 二、如何下载 1.点击File—>Settings ​2.点击Plugins然后进行搜索下载 三、Android Studio 模板 一、插件推荐 这个插件可以为您自动生成Parcelable代码。Parcelable是一种用于在Android组件之间传递自定义对象的机制&#xff0c;但手动编写Parcela…

dcoker-compose一键部署EFAK —— 筑梦之路

简介 EFAK&#xff08;Eagle For Apache Kafka&#xff0c;以前称为 Kafka Eagle&#xff09;是一款由国内公司开源的Kafka集群监控系统&#xff0c;可以用来监视kafka集群的broker状态、Topic信息、IO、内存、consumer线程、偏移量等信息&#xff0c;并进行可视化图表展示。独…

力扣刷题-二叉树-路径总和

112 路径总和 给定一个二叉树和一个目标和&#xff0c;判断该树中是否存在根节点到叶子节点的路径&#xff0c;这条路径上所有节点值相加等于目标和。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff0c;以及目标和 sum 22&#xff0c; 返回 true, 因为…

如何将数据库导入MySQL的办法

在电脑cmd终端进行导入 首先找到MySQL中bin的位置 第一步&#xff1a;找到MySQL 第二步&#xff1a;进入MySQL 第三步&#xff1a;打开bin 第四步&#xff1a;输入cmd进入终端 第五步&#xff1a; 输入mysql -uroot -p 然后会弹出enter password&#xff1a; 输入你的密码…

记一次挖矿病毒的溯源

ps&#xff1a;因为项目保密的原因部分的截图是自己在本地的环境复现。 1. 起因 客户打电话过来说&#xff0c;公司web服务异常卡顿。起初以为是web服务缓存过多导致&#xff0c;重启几次无果后觉得可能是受到了攻击。起初以为是ddos攻击&#xff0c;然后去查看web服务器管理…

基于ssm日用品网站设计论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本日用品网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

数字孪生项目的开发平台

WEBGL 开发数字孪生项目的流程涵盖了需求分析、场景搭建、模型创建、数据接入、动画与交互、性能优化、测试与部署以及维护与升级等方面。WEBGL 开发数字孪生项目的流程可以分为以下几个步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外…

SCI一区级 | Matlab实现GWO-CNN-GRU-selfAttention多变量多步时间序列预测

SCI一区级 | Matlab实现GWO-CNN-GRU-selfAttention多变量多步时间序列预测 目录 SCI一区级 | Matlab实现GWO-CNN-GRU-selfAttention多变量多步时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现GWO-CNN-GRU-selfAttention灰狼算法优化卷积门控循环…

ubuntu debian mini安装系统 有线选项消失或ens33 ethernet 未托管解决方法

nmcli device status#修改NetworkManager.conf如下 sed s/false/true/ /etc/NetworkManager/NetworkManager.confsed -i s/false/true/ /etc/NetworkManager/NetworkManager.conf#重启生效systemctl restart NetworkManager

Linux(23):Linux 核心编译与管理

编译前的任务&#xff1a;认识核心与取得核心原始码 Linux 其实指的是核心。这个【核心(kernel)】是整个操作系统的最底层&#xff0c;他负责了整个硬件的驱动&#xff0c;以及提供各种系统所需的核心功能&#xff0c;包括防火墙机制、是否支持 LVM 或 Quota 等文件系统等等&a…

【C++11特性篇】一文助小白轻松理解 C++中的【左值&左值引用】【右值&右值引用】

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.【左值&#xff06;左值引用】&…

MNIST内置手写数字数据集的实现

torchvision库 torchivision库是PyTorch中用来处理图像和视频的一个辅助库&#xff0c;接下来我们就会使用torchvision库加载内置的数据集进行分类模型的演示 为了统一数据加载和处理代码&#xff0c;PyTorch提供了两个类用于处理数据加载&#xff0c;他们分别是torch.utils.…