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

NET Core的AOP实施方法1 DispatchProxy

NET Core的AOP实施方法1 DispatchProxy
NET Framework的AOP实施方法1 ContextBoundObject
NET Framework的AOP实施方法2 RealProxy

源码见Github

DispatchProxy

NET Core
DispatchProxy 是一个在 .NET 框架中引入的概念,特别是在 C# 语言中。它是一种特殊类型的代理,用于在运行时动态地分派方法调用到不同的实现。DispatchProxy 类位于 System.Runtime.Remoting.Proxies 命名空间中,并且是 RealProxy 类的一个派生类。

以下是 DispatchProxy 的一些关键点:

动态分派:DispatchProxy 允许开发者在运行时决定将方法调用分派给哪个对象。这使得可以在不修改现有代码的情况下,动态地改变对象的行为。

透明代理:DispatchProxy 是一种透明代理,这意味着客户端代码不需要知道代理的存在。客户端代码可以直接调用方法,就像它们直接调用实际对象一样。

类型安全:尽管 DispatchProxy 是动态分派的,但它仍然保持类型安全。代理对象可以被强制转换为任何接口类型,并且只有那些接口上的方法调用才会被分派。

创建自定义代理:开发者可以通过继承 DispatchProxy 类并重写 Invoke 方法来创建自己的代理。在 Invoke 方法中,开发者可以决定如何分派方法调用,例如,基于调用的方法名、参数或其他逻辑。

性能开销:由于 DispatchProxy 涉及到运行时的动态分派,因此可能会有一些性能开销。因此,它更适合于那些性能不是主要关注点的场景。

用途:DispatchProxy 可以用于多种场景,包括但不限于日志记录、性能监控、事务管理、安全性检查、Mock对象的创建等。

相较于RealProxy和ContextBoundObject,DispatchProxy的实现更加便捷

创建日志拦截器

public class LoggingDecorator<T> : DispatchProxy
{private T _decorated;protected override object Invoke(MethodInfo methodInfo, object[] args){try{LogBefore(methodInfo, args);var result = methodInfo.Invoke(_decorated, args);if (methodInfo.IsAsyncMethod()){if (methodInfo.ReturnType == typeof(Task)){var task = (Task)result;var val = InternalAsyncHelper.AwaitTaskWithPostActionAndFinally(task,async () =>{Debug.WriteLine($"Task {methodInfo.Name} completed");}, /*成功时执行*/ex =>{if (ex != null){Debug.WriteLine($"Task {methodInfo.Name} threw an exception: {ex.ToString()}");}});return val;}else{var returnTypeGenericTypeArgument = methodInfo.ReturnType.GenericTypeArguments[0];var val = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult(returnTypeGenericTypeArgument,result,async (o) =>{Debug.WriteLine($"Task {methodInfo.Name} completed with result {o}");}, /*成功时执行*/ex =>{if (ex != null){Debug.WriteLine($"Task {methodInfo.Name} threw an exception: {ex.ToString()}");}});return val;}}else{LogAfter(methodInfo, args, result);}return result;}catch (Exception ex) when (ex is TargetInvocationException){LogException(ex.InnerException ?? ex, methodInfo);throw ex.InnerException ?? ex;}}public static T Create(T decorated){object proxy = Create<T, LoggingDecorator<T>>();((LoggingDecorator<T>)proxy).SetParameters(decorated);return (T)proxy;}private void SetParameters(T decorated){if (decorated == null){throw new ArgumentNullException(nameof(decorated));}_decorated = decorated;}private void LogException(Exception exception, MethodInfo methodInfo = null){Console.WriteLine($"Class {_decorated.GetType().FullName}, Method {methodInfo.Name} threw exception:\n{exception}");}private void LogAfter(MethodInfo methodInfo, object[] args, object result){Console.WriteLine($"Class {_decorated.GetType().FullName}, Method {methodInfo.Name} executed, Output: {result}");}private void LogBefore(MethodInfo methodInfo, object[] args){Console.WriteLine($"Class {_decorated.GetType().FullName}, Method {methodInfo.Name} is executing");}
}

代理异步的帮助类

internal static class InternalAsyncHelper
{public static bool IsAsyncMethod(this MethodInfo method){return method.ReturnType == typeof(Task)|| method.ReturnType.IsGenericType&& method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>);}public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue,Func<Task> postAction,Action<Exception> finalAction){Exception exception = null;try{await actualReturnValue;await postAction();}catch (Exception ex){exception = ex;}finally{finalAction(exception);}}public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue,Func<object, Task> postAction,Action<Exception> finalAction){Exception exception = null;try{var result = await actualReturnValue;await postAction(result);return result;}catch (Exception ex){exception = ex;throw;}finally{finalAction(exception);}}public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType,object actualReturnValue,Func<object, Task> action,Action<Exception> finalAction){//AwaitTaskWithPostActionAndFinallyAndGetResult<taskReturnType>(actualReturnValue, action, finalAction);return typeof(InternalAsyncHelper).GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult",BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(taskReturnType).Invoke(null, new object[] { actualReturnValue, action, finalAction });}
}

声明及调用示例

public interface ICalculator
{int Add(int a, int b);Task<int> AddAsync(int a, int b);
}
public class Calculator : ICalculator
{public int Add(int a, int b){//throw new NotImplementedException("This method is not implemented. sorry!");return a + b;}public async Task<int> AddAsync(int a, int b){await Task.Delay(1000);return a + b;}
}

示例

var decoratedCalculator = LoggingDecorator<ICalculator>.Create(new Calculator());
decoratedCalculator.Add(3, 5);
Console.WriteLine($"Started at {DateTime.Now:HH:mm:ss.fff}");
var res =decoratedCalculator.AddAsync(2, 4);Console.WriteLine("Waiting for 1 seconds for querying customer...");
Console.WriteLine($"Querying {DateTime.Now:HH:mm:ss.fff}");
Console.WriteLine(res.GetAwaiter().GetResult());
Console.WriteLine($"Finished at {DateTime.Now:HH:mm:ss.fff}");

相关文章:

NET Core的AOP实施方法1 DispatchProxy

NET Core的AOP实施方法1 DispatchProxy NET Framework的AOP实施方法1 ContextBoundObject NET Framework的AOP实施方法2 RealProxy 源码见Github DispatchProxy NET Core DispatchProxy 是一个在 .NET 框架中引入的概念&#xff0c;特别是在 C# 语言中。它是一种特殊类型的代…...

AIGC生成式人工智能——泼天的富贵(三)

人工智能作为第四次工业革命的标志性技术&#xff0c;正在深刻地改变着全球经济、社会结构和人类生活方式。 今天的人工智能&#xff0c;就像当年的房地产经济&#xff0c;未来至少会有十年的红利期。 一、人工智能&#xff0c;给我带来了第二桶金 你永远赚不到你认知以外的…...

GetX的一些高级API

目录 前言 一、一些常用的API 二、局部状态组件 1.可选的全局设置和手动配置 2.局部状态组件 1.ValueBuilder 1.特点 2.基本用法 2.ObxValue 1.特点 2.基本用法 前言 这篇文章主要讲解GetX的一些高级API和一些有用的小组件。 一、一些常用的API GetX提供了一些高级…...

【笔面试常见题:三门问题】用条件概率、全概率和贝叶斯推导

1. 问题介绍 三门问题&#xff0c;又叫蒙提霍尔问题&#xff08;Monty Hall problem&#xff09;&#xff0c;以下是蒙提霍尔问题的一个著名的叙述&#xff0c;来自Craig F. Whitaker于1990年寄给《展示杂志》&#xff08;Parade Magazine&#xff09;玛丽莲沃斯莎凡特&#x…...

刘艳兵-DBA011-应用使用Oracle数据库,必须启动哪些服务?

应用使用Oracle数据库&#xff0c;必须启动哪些服务&#xff08; &#xff09; A OracleServiceSID B OracleJobSchedulerSID C OracleMTSRecoveryService D OracleHOME_NAMETNSListener 答&#xff1a; A OracleServiceSID D OracleHOME_NAMETNSListener…...

注释多行代码的vim插件

编写vim 插件代码 add_comments.vim function! AddComment()let l:comment #if &filetype cpplet l:comment //elseif &filetype clet l:comment //endiflet [l:start, l:end][ line("<"), line(">") ]let l:commented_lines []for …...

Docker 安装HomeAssistant智能家居系统

HomeAssistant 介绍 简介 Home Assistant是一个自由开源的智能家居自动化平台&#xff0c;它可以控制并监测各种智能家居设备、传感器和其他物联网设备。Home Assistant可以运行在树莓派、NVIDIA Jetson Nano等低功耗设备上&#xff0c;使用户可以快速搭建自己的智能家居系统。…...

21 Docker容器集群网络架构:四、Docker集群网络验证

文章目录 Docker容器集群网络架构:四、Docker集群网络验证4.1 创建网络4.2 查看创建的网络4.2.1 查看节点1创建的网络4.2.2 查看节点2创建的网络4.2.3 查看节点3创建的网络4.3 运行容器并查看4.3.1 运行容器4.3.2 节点1查看4.3.3 节点2查看4.3.4 节点3查看Docker容器集群网络架…...

【Kaggle | Pandas】练习5:数据类型和缺失值

文章目录 1. 获取列数据类型.dtype / .dypes2. 转换数据类型.astype()3. 获取数据为空的列 .isnull()4. 将缺少值替换并且排序.fillna()&#xff0c;.sort_values() 1. 获取列数据类型.dtype / .dypes 数据集中points列的数据类型是什么&#xff1f; # Your code here dtype …...

《YOLO 目标检测》—— YOLO v4 详细介绍

文章目录 一、整体网络结构1. YOLO v4 网络结构图2.对之前版本改进创新的概括 二、对改进创新部分的具体介绍1. 输入端创新2. Backbone主干网络创新CSPDarknet53Mish激活函数Dropblock正则化 3. 特征融合创新SPP模块PAN结构 4. Prediction输出层创新&#xff08;未写完&#xf…...

Ubuntu:通过ssh链接另外一台Ubuntu

本文将介绍通过ssh链接另外一台Ubuntu的方法。 一、安装openssh-server sudo apt update sudo apt install openssh-server二、查看SSH是否运行 sudo systemctl status ssh三、链接 ssh usernameremote_ip_address四、复制A电脑的文件到本地 scp usernameremote_ip_addres…...

黄山谷捷提交创业板IPO注册,募资扩产提升综合竞争力

近日&#xff0c;黄山谷捷股份有限公司&#xff08;下文称“黄山谷捷”&#xff09;申请深交所创业板IPO审核状态变更为“提交注册”。据悉&#xff0c;本次IPO黄山谷捷拟募资50,201.19万元&#xff0c;分别用于功率半导体模块散热基板智能制造及产能提升项目&#xff0c;研发中…...

(python)如何进行加密

代码效果是将输入的四个数字每个加上7&#xff0c;然后除以10的余数&#xff0c;接着再将第一个数字和第三个数字对调&#xff0c;第二个数字和第四个数字对调 # 获取用户输入的四位数字符串 list1 input("请输入你四位数密码&#xff1a;") # 初始化一个空列表来存…...

夸克网盘免费扩容 20T 福利,无限次叠加,亲测有效

新用户用夸克 APP 存资源可得 1T 永久存储空间 &#x1f6a8;此方法仅试用于新用户&#xff0c;并且只能在手机上打开夸克 APP 中去领取&#xff01;pc&#xff0c;ipad 都不行&#xff01;&#xff01;&#xff01; 使用手机打开夸克 APP&#xff0c;保存以下资源可获取 1T …...

开源协议类型及长安链开源协议介绍

截至目前&#xff0c;我国参与国际开源社区协作的开发者数量排名全球第二并推出了众多社区活跃度较高的高质量开源项目&#xff0c;是全球开源生态的重要贡献力量&#xff0c;但在开源治理方面我国还处于发展初期&#xff0c;大部分开发者对开源的印象还限于开放代码、免费使用…...

SQL Server 可观测最佳实践

SQL Server 简介 SQL Server 是微软公司开发的一款关系数据库管理系统&#xff0c;支持企业 IT 环境中的各种事务处理、商业智能和分析应用程序。它支持多种操作系统平台&#xff0c;而无论是物理还是虚拟形式&#xff0c;自建部署环境还是在云环境中&#xff0c;运行的操作系…...

青少年编程能力等级测评CPA Python编程(一级)

青少年编程能力等级测评CPA Python编程(一级) &#xff08;考试时间90分钟&#xff0c;满分100分&#xff09; 一、单项选择题&#xff08;共20题&#xff0c;每题3.5分&#xff0c;共70分&#xff09; 下列语句的输出结果是&#xff08; &#xff09;。 print(35*2) A&a…...

WebSocket 连接频繁断开的问题及解决方案

文章目录 WebSocket 连接频繁断开的问题及解决方案1. 引言2. 什么是 WebSocket&#xff1f;2.1 WebSocket 的优势2.2 WebSocket 的工作原理 3. WebSocket 连接频繁断开的常见原因3.1 服务器端问题3.1.1 服务器负载过高3.1.2 服务器配置不当3.1.3 超时设置 3.2 网络问题3.2.1 网…...

[CSP篇] CSP2024 游记(上)

Part.0 前言 在刚刚过去的 CSP-J2024 以及 CSP-S2024 中&#xff0c;不知大家十分用自己最好的状态参加了这次重要的测试&#xff0c;取得了令自己努力的成绩呢&#xff1f; 文章发布在 2024 年 11 月 1 日&#xff0c;距离出结果还有 3 − 5 3-5 3−5 天&#xff0c;如有需…...

Mac “屏幕保护程序启动或显示器关闭后需要密码“无效

屏幕保护程序启动或显示器关闭后需要密码只能选择“立即”的解决方法&#xff1a; 在 iPhone mirror中设置&#xff0c;每次询问权限。 参考&#xff1a;https://support.apple.com/en-us/120421...

JVM 内存管理 2026:深度解析与调优实战

JVM 内存管理 2026&#xff1a;深度解析与调优实战我是 Alex&#xff0c;一个在 CSDN 写 Java 架构思考的暖男。看到新手博主写技术踩坑记录总会留言&#xff1a;"这个 debug 思路很 solid&#xff0c;下次试试加个 circuit breaker 会更优雅。"我的文章里从不说空话…...

linux下的spi子系统

概念通信模式可以分为单工、半双工和全双工&#xff0c;单工通信指信号只在一个方向上传输&#xff0c;仅 能发送或接收&#xff0c;而半双工通信指信号可以在俩个方向上传输&#xff0c;但某一个时刻只允许发送或接收&#xff0c;而全双工通信指数据同时在俩个方向上传输&…...

KS-Downloader:快手无水印内容获取与管理的专业解决方案

KS-Downloader&#xff1a;快手无水印内容获取与管理的专业解决方案 【免费下载链接】KS-Downloader 快手&#xff08;KuaiShou&#xff09;视频/图片下载工具&#xff1b;数据采集工具 项目地址: https://gitcode.com/gh_mirrors/ks/KS-Downloader 在短视频内容创作与传…...

2025届必备的AI学术方案实际效果

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在当下的学术写作情形里&#xff0c;免费的人工智能论文工具达成了从文献查找、大纲制作直至…...

EPSON RX8010SJ RTC与Nordic TWI实战:I2C通讯时序详解与避坑指南

EPSON RX8010SJ RTC与Nordic TWI实战&#xff1a;I2C通讯时序详解与避坑指南 在嵌入式系统中&#xff0c;实时时钟&#xff08;RTC&#xff09;模块是许多应用的核心组件之一。EPSON RX8010SJ作为一款低功耗、高精度的RTC芯片&#xff0c;广泛应用于物联网设备、可穿戴设备和工…...

前端Word文档生成革命:3分钟掌握纯JavaScript专业文档导出创新方案

前端Word文档生成革命&#xff1a;3分钟掌握纯JavaScript专业文档导出创新方案 【免费下载链接】DOCX.js Generate Microsoft Word DOCX files in pure client-side JavaScript. Try in Chrome 项目地址: https://gitcode.com/gh_mirrors/do/DOCX.js 还在为Word文档导出…...

KW45芯片的安全启动

KW45芯片的安全启动是一个硬件强制执行的完整性验证机制&#xff0c;确保芯片始终只运行由设备所有者&#xff08;OEM&#xff09;授权和签名的固件。它的核心目标是防止未授权或恶意代码在设备上执行&#xff0c;是构建设备安全体系的基石。&#x1f6e1;️ 安全启动的核心机制…...

【ComfyUI】Qwen-Image-Edit-F2P用于影视概念设计:快速生成角色面部概念图

ComfyUI Qwen-Image-Edit-F2P用于影视概念设计&#xff1a;快速生成角色面部概念图 1. 引言&#xff1a;当AI画笔遇见影视美术 想象一下这个场景&#xff1a;一部新剧的美术指导正在为“饱经风霜的西部枪手”这个角色发愁。导演想要一张能瞬间抓住观众眼球的脸&#xff0c;一…...

m4s-converter:让B站缓存重获新生的轻量级格式转换工具

m4s-converter&#xff1a;让B站缓存重获新生的轻量级格式转换工具 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 当你辛苦缓存的B站视频因下架…...

OpenClaw+Phi-3-vision-128k-instruct医疗辅助:医学影像报告自动生成系统

OpenClawPhi-3-vision-128k-instruct医疗辅助&#xff1a;医学影像报告自动生成系统 1. 医疗AI落地的隐私合规挑战 去年参与某三甲医院科研项目时&#xff0c;我深刻体会到医疗AI落地的核心矛盾——技术潜力与隐私合规的冲突。当时我们需要处理数千份CT影像&#xff0c;传统人…...