🌟 .NET ExpandoObject 技术原理解析
引用:
- .NET 剖析4.0上ExpandoObject动态扩展对象原理
- 风潇潇人渺渺
- 快意刀山中草
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 元对象提供器实现原理
csharp
DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression express)
{
return new ExpandoMetaObject(this, express);
}
DLR运行时 ExpandoObject ExpandoMetaObject 请求MetaObject(Expression) 创建ExpandoMetaObject(this, express) 返回ExpandoMetaObject实例 调用绑定方法(BindGetMember等) 返回DynamicMetaObject(表达式树) 编译执行表达式树 DLR运行时 ExpandoObject ExpandoMetaObject
2.2 表达式树构建技术
绑定方法 InvokeMember调用 创建表达式树 Expression.Call 目标对象: this 方法: Set/Get/Invoke 参数1: key常量 参数2: value常量
实际表达式树创建代码:
csharp
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 字典_dict var value = obj.Name BindGetMember("Name") 调用InvokeMember("Name", getMethod) 返回表达式树 编译并执行表达式树 调用Get("Name", null) lock(_dict) 返回dict["Name"] 抛出MemberAccessException alt [存在键] [不存在键] 返回结果 返回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 改进后的锁策略
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 字典操作 锁保护 反射方法缓存 枚举器快照 枚举安全 无锁字典 减少锁范围 委托缓存 原始实现 优化建议 关键改进点 线程安全优化方案
改进后枚举实现:
csharp
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
lock (_dict)
{
// 创建副本保证线程安全
return new List<string>(_dict.Keys).GetEnumerator();
}
}
⚡ 五、性能优化深度分析
5.1 反射优化策略
原始实现 每次绑定调用GetMethod 运行时反射 高开销 优化建议 静态构造函数预加载 MethodInfo缓存 减少运行时开销
csharp
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 架构差异对比图
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进化路线