🌟 .NET ExpandoObject 技术原理解析

引用

  1. .NET 剖析4.0上ExpandoObject动态扩展对象原理
  2. 风潇潇人渺渺
  3. 快意刀山中草
ExpandoObject
IDynamicMetaObjectProvider
IEnumerable
字段_dict
IDictionary
嵌套类ExpandoMetaObject
DynamicMetaObject
方法Set/Get/Invoke
绑定方法BindGetMember等
反射方法缓存

🧠 一、总体架构设计(核心组件分析)

1.1 类关系拓扑图

创建
继承
实现
实现
«sealed»
ExpandoObject
+IDictionary _dict
+IDynamicMetaObjectProvider.GetMetaObject()
+IEnumerable.GetEnumerator()
+IEnumerable.GetEnumerator()
ExpandoMetaObject
-IDictionary dict
+BindGetMember(GetMemberBinder) : DynamicMetaObject
+BindSetMember(SetMemberBinder, DynamicMetaObject) : DynamicMetaObject
+BindInvokeMember(InvokeMemberBinder, DynamicMetaObject[]) : DynamicMetaObject
-Get(string, object) : object
-Set(string, object) : object
-Invoke(string, object) : object
«abstract»
DynamicMetaObject
+Expression Expression
+BindingRestrictions Restrictions
+object Value
+BindGetMember(GetMemberBinder) : DynamicMetaObject
+BindSetMember(SetMemberBinder, DynamicMetaObject) : DynamicMetaObject
+BindInvokeMember(InvokeMemberBinder, DynamicMetaObject[]) : DynamicMetaObject
IDynamicMetaObjectProvider
IEnumerable<string>

1.2 核心数据流架构

数据存储
执行层
DLR层
用户层
属性访问
属性设置
方法调用
Dict读写
线程同步
最终结果
构建表达式树
创建DynamicMetaObject
DLR执行引擎
实际调用Set/Get/Invoke
操作字典数据
GetMemberBinder
SetMemberBinder
InvokeMemberBinder
ExpandoMetaObject.BindGetMember
ExpandoMetaObject.BindSetMember
ExpandoMetaObject.BindInvokeMember
操作类型
动态操作

🛠 二、动态绑定机制深度解析

2.1 元对象提供器实现原理

DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression express)
{return new ExpandoMetaObject(this, express);
}
DLR运行时ExpandoObjectExpandoMetaObject请求MetaObject(Expression)创建ExpandoMetaObject(this, express)返回ExpandoMetaObject实例调用绑定方法(BindGetMember等)返回DynamicMetaObject(表达式树)编译执行表达式树DLR运行时ExpandoObjectExpandoMetaObject

2.2 表达式树构建技术

绑定方法
InvokeMember调用
创建表达式树
Expression.Call
目标对象: this
方法: Set/Get/Invoke
参数1: key常量
参数2: value常量

实际表达式树创建代码:

private DynamicMetaObject InvokeMember(string key, MethodInfo met, params object[] values)
{// 参数处理逻辑object args = null;if (met == invoke) args = values;else if (values != null && values.Length > 0) args = values[0];// 构建表达式树核心return new DynamicMetaObject(Expression.Call(Expression.Constant(this),  // 目标对象met,                        // 方法信息Expression.Constant(key, typeof(string)), // 成员名Expression.Convert(Expression.Constant(args), typeof(object)) // 值),BindingRestrictions.GetTypeRestriction(base.Expression, base.LimitType));
}

🔍 三、成员操作深度分析

3.1 属性获取机制(Get)

用户代码DLR运行时ExpandoMetaObject字典_dictvar value = obj.NameBindGetMember("Name")调用InvokeMember("Name", getMethod)返回表达式树编译并执行表达式树调用Get("Name", null)lock(_dict)返回dict["Name"]抛出MemberAccessExceptionalt[存在键][不存在键]返回结果返回value用户代码DLR运行时ExpandoMetaObject字典_dict

3.2 属性设置机制(Set)

在这里插入图片描述

3.3 方法调用机制(Invoke)

调用Invoke方法
成员存在?
检查类型
检查
BindInvokeMember
参数转换:
收集所有参数
参数转换
InvokeMember:
传递方法名和参数
InvokeMember
构建表达式树
返回DynamicMetaObject
执行表达式树
获取锁
检查成员存在
存在
获取值
不存在
抛出异常
是委托?
是:
动态调用
否:
抛MethodAccessException
DynamicInvoke
返回结果

🔒 四、线程安全与锁机制

4.1 锁的应用全景图

潜在问题
安全访问
锁保护区域
返回原始迭代器
在枚举期间修改字典可能导致异常
临界区操作
字典存在检查
键值读取
键值设置
委托获取
键集合枚举
lock(_dict)
Get操作
Set操作
Invoke操作
枚举操作

4.2 改进后的锁策略

01234567891011121314151617181920字典操作 锁保护 反射方法缓存 枚举器快照 枚举安全 无锁字典 减少锁范围 委托缓存 原始实现优化建议关键改进点线程安全优化方案

改进后枚举实现:

IEnumerator<string> IEnumerable<string>.GetEnumerator()
{lock (_dict){// 创建副本保证线程安全return new List<string>(_dict.Keys).GetEnumerator();}
}

⚡ 五、性能优化深度分析

5.1 反射优化策略

原始实现
每次绑定调用GetMethod
运行时反射
高开销
优化建议
静态构造函数预加载
MethodInfo缓存
减少运行时开销
private static class MethodCache
{public static readonly MethodInfo SetMethod;public static readonly MethodInfo GetMethod;public static readonly MethodInfo InvokeMethod;static MethodCache(){SetMethod = typeof(ExpandoMetaObject).GetMethod("Set", BindingFlags.NonPublic | BindingFlags.Instance);// ...同理缓存其他方法}
}

5.2 表达式树编译缓存

第一次调用
构建表达式树
编译为委托
执行委托
后续调用
使用缓存委托

5.3 内存占用分析

45%25%15%10%5%内存占用分布字典存储表达式树元数据开销委托对象其他

🆚 六、与官方实现对比分析

6.1 架构差异对比图

mindmaproot((架构差异))线程同步🟢 此实现:全局lock🔵 官方实现:无锁CAS成员枚举🔴 此实现:原始迭代器🟢 官方实现:键集合快照元数据处理🟠 此实现:每次构建🟢 官方实现:缓存优化动态方法🟢 两者相同:基于委托错误处理🟠 此实现:基本异常🟢 官方实现:详细异常信息

6.2 性能基准对比

在这里插入图片描述


🛡 七、最佳实践与安全性

7.1 线程安全使用模式

只读线程
读写线程
创建ExpandoObject
写入初始化数据
多线程访问
安全
外部同步
使用外部锁
避免嵌套锁

7.2 异常处理体系

«异常体系»
DynamicExceptions
+MemberAccessException: 成员不存在
+MethodAccessException: 非委托调用
+TargetInvocationException: 委托异常
+InvalidOperationException: 枚举修改
MemberAccessException
MethodAccessException
TargetInvocationException
InvalidOperationException

🔮 八、高级应用场景

8.1 动态工作流引擎集成

条件满足
条件不满足
JSON配置
解析为ExpandoObject
动态添加方法
创建工作流
执行步骤
判断条件
执行下一节点
执行备选分支

8.2 动态规则引擎实现

用户规则API规则引擎ExpandoObject定义规则({condition: "Age >= 18", action: "Approve"})添加规则(规则对象)提交请求(用户数据)转换为动态对象添加验证方法条件结果执行对应操作alt[条件验证]返回结果loop[执行规则]用户规则API规则引擎ExpandoObject

💎 九、总结与展望

9.1 技术实现矩阵

在这里插入图片描述

9.2 未来发展建议

-.NET Core优化=等this[key]访问分段锁策略基于ImmutableDictionary支持+缓存MethodInfo返回快照预编译动态方法
基础优化
基础优化
缓存MethodInfo
反射优化
反射优化
返回快照
枚举安全
枚举安全
分段锁策略
减少锁竞争
减少锁竞争
高级特性
高级特性
this[key]访问
索引器支持
索引器支持
支持+-=等
动态操作符
动态操作符
.NET Core优化
跨平台兼容
跨平台兼容
性能突破
性能突破
基于ImmutableDictionary
无锁实现
无锁实现
预编译动态方法
AOT支持
AOT支持
ExpandoObject进化路线

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

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

相关文章

放苹果(信息学奥赛一本通-T1192)

【题目描述】把M个同样的苹果放在N个同样的盘子里&#xff0c;允许有的盘子空着不放&#xff0c;问共有多少种不同的分法&#xff1f;&#xff08;用K表示&#xff09;5&#xff0c;1&#xff0c;1和1&#xff0c;5&#xff0c;1 是同一种分法。【输入】第一行是测试数据的数目…

(懒人救星版)CNN_Kriging_NSGA2_Topsis(多模型融合典范)深度学习+SCI热点模型+多目标+熵权法 全网首例,完全原创,早用早发SCI

全网首例&#xff0c;完全原创&#xff0c;早用早发SCI&#xff08;多模型融合典范&#xff09;机器学习SCI热点模型多目标熵权法(懒人救星版)BP_Kriging_NSGA2_Topsis 改进克里金工作量大&#xff1a;多模型融合创新性&#xff1a;首次结合BP神经网络和克里金多目标利用 BP神…

LeetCode热题100【第一天】

第一题 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回…

AI Linux 运维笔记

运维基本概念 IT运维是指通过专业技术手段&#xff0c;确保企业的IT系统和网络持续、安全、稳定运行&#xff0c;保障业务的连续性。运维涵盖计算机网络、应用系统、硬件环境和服务流程的综合管理。主要分为: 系统运维、数据库运维、自动化运维、容器运维、云计算运维、信创运维…

Redis性能基准测试

基准环境 机器&#xff1a;AWS EC2 c4.8xlarge&#xff08;同机部署 Redis Server 与 ReJSONBenchmark 工具&#xff0c;通过网络栈连接&#xff09;测试工具&#xff1a;ReJSONBenchmark&#xff08;Go 实现、可配置并发&#xff09;模式&#xff1a;非管线&#xff08;non-pi…

XML外部实体注入与修复方案

XML外部实体注入&#xff08;XXE&#xff09;是一种严重的安全漏洞&#xff0c;攻击者利用XML解析器处理外部实体的功能来读取服务器内部文件、执行远程请求&#xff08;SSRF&#xff09;、扫描内网端口或发起拒绝服务攻击。以下是详细解释和修复方案&#xff1a;XXE 攻击原理外…

解决高并发场景中的连接延迟:TCP 优化与队头阻塞问题剖析

你是否在高并发场景下遇到过这种情况&#xff1a;系统性能本来不错&#xff0c;但在请求量大增的时刻&#xff0c;连接延迟暴涨&#xff0c;响应时间直线飙升&#xff0c;甚至整个服务都变得不可用&#xff1f;当你打开监控时&#xff0c;CPU、内存、带宽都在正常范围内&#x…

Web学习笔记4

CSS概述1、CSS简介CSS&#xff0c;层叠样式表&#xff0c;是一种样式表语言&#xff0c;用以描述HTML的呈现内容的方式&#xff08;美化网页&#xff09;。CSS书写规则是&#xff1a;选择器{属性名&#xff1a;属性值}的键值对CSS有三种引入方式&#xff0c;分别为&#xff1a;…

Spring AI 初学者指南:从入门到实践与常用大模型介绍

作为 Java 开发者&#xff0c;当 AI 浪潮席卷而来时&#xff0c;如何在熟悉的 Spring 生态中快速拥抱大模型开发&#xff1f;Spring AI 的出现给出了答案。本文将从初学者视角出发&#xff0c;带你了解 Spring AI 的核心概念、使用方法&#xff0c;并介绍与之搭配的常用大模型&…

C#自定义控件

1。C#中控件和组件的区别&#xff1a; 一般组件派生于&#xff1a;Component类&#xff0c;所以从此类派生出的称之为组件。 一般用户控件派生于:Control类或UserControl类&#xff0c;所以从该类派生出的称之为用户控件。 他们之间的关系主要是&#xff1a;UserControl继承Con…

网络资产测绘工具全景解析:七大平台深度洞察

​一、资产测绘工具的核心价值​网络资产测绘&#xff08;Cyber Asset Intelligence&#xff09;技术通过主动扫描与被动分析&#xff1a;实时发现全球暴露的网络设备&#xff08;服务器、摄像头、IoT设备&#xff09;自动化构建资产指纹库&#xff08;操作系统/服务/框架版本&…

编程语言设计目的与侧重点全解析(主流语言深度总结)

编程语言的设计本质上是对计算逻辑的形式化表达与工程约束的平衡&#xff0c;不同语言因目标场景、时代需求和技术哲学的差异&#xff0c;形成了独特的设计范式。以下从系统级、应用级、脚本/动态、函数式、并发/安全等维度&#xff0c;选取10种最具代表性的编程语言&#xff0…

重学前端003 --- 响应式网页设计 CSS 颜色

文章目录文档声明head颜色模型div根据在这里 Freecodecamp 实践&#xff0c;记录笔记总结。 文档声明 在文档顶部添加 DOCTYPE html 声明 <!DOCTYPE html>head title 元素为搜索引擎提供了有关页面的额外信息。 它还通过以下两种方式显示 title 元素的内容&#xff1a…

这个Pandas函数可以自动爬取Web图表

Pandas作为数据科学领域鳌头独占的利器&#xff0c;有着丰富多样的函数&#xff0c;能实现各种意想不到的功能。 作为学习者没办法一次性掌握Pandas所有的方法&#xff0c;需要慢慢积累&#xff0c;多看多练。 这次为大家介绍一个非常实用且神奇的函数-read_html()&#xff0…

vLLM与SGLang在自然语言处理领域的技术架构与性能对比研究

随着大语言模型在工业界和学术界的广泛应用&#xff0c;高效推理框架的选择成为自然语言处理领域的关键挑战。vLLM与SGLang作为当前最前沿的推理优化框架&#xff0c;分别通过创新的PagedAttention和RadixAttention机制展现了独特的技术优势。本文将系统对比两大框架的核心架构…

楼宇自动化:Modbus 在暖通空调(HVAC)中的节能控制(二)

Modbus 在 HVAC 节能控制中的应用案例案例一&#xff1a;某商业建筑 HVAC 系统节能改造某大型商业建筑&#xff0c;总建筑面积达 5 万平方米&#xff0c;涵盖了购物中心、餐饮区和娱乐场所等多种功能区域 。改造前&#xff0c;其 HVAC 系统采用传统的控制方式&#xff0c;设备之…

win10安装Elasticsearch

1 启动elasticsearch 下载地址&#xff1a;Download Elasticsearch | Elastic 双击elasticsearch.bat elasticsearch黑窗口启动乱码问题解决方案 到 config 文件下找到 jvm.options 文件 打开后 在文件末尾空白处 添加 -Dfile.encodingGBK 保存后重启即可。 启动后输入&am…

[Meetily后端框架] Whisper转录服务器 | 后端服务管理脚本

第七章&#xff1a;Whisper转录服务器 欢迎回来&#xff01; 到目前为止&#xff0c;我们已经深入探索了"meeting-minutes"项目的"大脑"——Python后端。 我们已经了解了它如何通过后端API网关接收文本转录&#xff0c;使用摘要数据结构&#xff08;Pyd…

Azure-ADF 抽取数据

1,Azure 访问地址 1,国际版 https://portal.azure.com/#homehttps://portal.azure.com/#home2,世纪互联中国版 Microsoft Azure 由世纪互联运营https://portal.azure.cn/2,创建资源组并且所有的后续组件都是再此资源下面创建。 3,创建Data Factory 工具 4,核心组件 1. 管…

django queryset 去重

在Django中&#xff0c;使用QuerySet时&#xff0c;如果你想要对查询结果进行去重&#xff08;即去除重复的记录&#xff09;&#xff0c;你可以使用几种不同的方法。这里列出了一些常见的方法&#xff1a; 使用distinct() distinct()方法用于返回QuerySet中不重复的唯一对象。…