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 框架中引入的概念,特别是在 C# 语言中。它是一种特殊类型的代…...
AIGC生成式人工智能——泼天的富贵(三)
人工智能作为第四次工业革命的标志性技术,正在深刻地改变着全球经济、社会结构和人类生活方式。 今天的人工智能,就像当年的房地产经济,未来至少会有十年的红利期。 一、人工智能,给我带来了第二桶金 你永远赚不到你认知以外的…...
GetX的一些高级API
目录 前言 一、一些常用的API 二、局部状态组件 1.可选的全局设置和手动配置 2.局部状态组件 1.ValueBuilder 1.特点 2.基本用法 2.ObxValue 1.特点 2.基本用法 前言 这篇文章主要讲解GetX的一些高级API和一些有用的小组件。 一、一些常用的API GetX提供了一些高级…...
【笔面试常见题:三门问题】用条件概率、全概率和贝叶斯推导
1. 问题介绍 三门问题,又叫蒙提霍尔问题(Monty Hall problem),以下是蒙提霍尔问题的一个著名的叙述,来自Craig F. Whitaker于1990年寄给《展示杂志》(Parade Magazine)玛丽莲沃斯莎凡特&#x…...
刘艳兵-DBA011-应用使用Oracle数据库,必须启动哪些服务?
应用使用Oracle数据库,必须启动哪些服务( ) A OracleServiceSID B OracleJobSchedulerSID C OracleMTSRecoveryService D OracleHOME_NAMETNSListener 答: 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是一个自由开源的智能家居自动化平台,它可以控制并监测各种智能家居设备、传感器和其他物联网设备。Home Assistant可以运行在树莓派、NVIDIA Jetson Nano等低功耗设备上,使用户可以快速搭建自己的智能家居系统。…...
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(),.sort_values() 1. 获取列数据类型.dtype / .dypes 数据集中points列的数据类型是什么? # Your code here dtype …...
《YOLO 目标检测》—— YOLO v4 详细介绍
文章目录 一、整体网络结构1. YOLO v4 网络结构图2.对之前版本改进创新的概括 二、对改进创新部分的具体介绍1. 输入端创新2. Backbone主干网络创新CSPDarknet53Mish激活函数Dropblock正则化 3. 特征融合创新SPP模块PAN结构 4. Prediction输出层创新(未写完…...
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注册,募资扩产提升综合竞争力
近日,黄山谷捷股份有限公司(下文称“黄山谷捷”)申请深交所创业板IPO审核状态变更为“提交注册”。据悉,本次IPO黄山谷捷拟募资50,201.19万元,分别用于功率半导体模块散热基板智能制造及产能提升项目,研发中…...
(python)如何进行加密
代码效果是将输入的四个数字每个加上7,然后除以10的余数,接着再将第一个数字和第三个数字对调,第二个数字和第四个数字对调 # 获取用户输入的四位数字符串 list1 input("请输入你四位数密码:") # 初始化一个空列表来存…...
夸克网盘免费扩容 20T 福利,无限次叠加,亲测有效
新用户用夸克 APP 存资源可得 1T 永久存储空间 🚨此方法仅试用于新用户,并且只能在手机上打开夸克 APP 中去领取!pc,ipad 都不行!!! 使用手机打开夸克 APP,保存以下资源可获取 1T …...
开源协议类型及长安链开源协议介绍
截至目前,我国参与国际开源社区协作的开发者数量排名全球第二并推出了众多社区活跃度较高的高质量开源项目,是全球开源生态的重要贡献力量,但在开源治理方面我国还处于发展初期,大部分开发者对开源的印象还限于开放代码、免费使用…...
SQL Server 可观测最佳实践
SQL Server 简介 SQL Server 是微软公司开发的一款关系数据库管理系统,支持企业 IT 环境中的各种事务处理、商业智能和分析应用程序。它支持多种操作系统平台,而无论是物理还是虚拟形式,自建部署环境还是在云环境中,运行的操作系…...
青少年编程能力等级测评CPA Python编程(一级)
青少年编程能力等级测评CPA Python编程(一级) (考试时间90分钟,满分100分) 一、单项选择题(共20题,每题3.5分,共70分) 下列语句的输出结果是( )。 print(35*2) A&a…...
WebSocket 连接频繁断开的问题及解决方案
文章目录 WebSocket 连接频繁断开的问题及解决方案1. 引言2. 什么是 WebSocket?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 中,不知大家十分用自己最好的状态参加了这次重要的测试,取得了令自己努力的成绩呢? 文章发布在 2024 年 11 月 1 日,距离出结果还有 3 − 5 3-5 3−5 天,如有需…...
Mac “屏幕保护程序启动或显示器关闭后需要密码“无效
屏幕保护程序启动或显示器关闭后需要密码只能选择“立即”的解决方法: 在 iPhone mirror中设置,每次询问权限。 参考:https://support.apple.com/en-us/120421...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
