Dynamic Linq在DynamicClass列表上查询失效问题及替代方案咨询
问题根因
这个异常和编码没有关系,核心原因是Dynamic Linq对动态生成类的字符串比较默认走引用相等判断逻辑:
- 你直接硬编码写
field.Value = "firstValue"时,赋值的字符串和查询语句中写的"firstValue"字面量都是编译期常量,会被CLR自动存入字符串驻留池,两个变量指向同一个内存地址,所以比较返回true - 从外部数据源读取的值、经过编码转码生成的字符串,都是运行时新创建的独立字符串对象,不会自动进入驻留池,和查询语句里的字面量不是同一个引用,默认的引用比较逻辑就会返回false。你用编码转码逻辑复现问题,本质只是生成了一个新的非驻留字符串,和编码转换本身没有关联。
解决方案
- 调整查询写法,强制走字符串值比较
不要用默认的eq运算符直接比较字符串,改为调用字符串的Equals方法做值匹配,代码示例:
也可以在初始化Dynamic Linq的解析配置时,开启字符串默认值比较的配置项,全局解决所有字符串比较的引用判断问题。bool isValid = query.Any("firstName.Equals(\"firstValue\")"); - 对存入动态类的字符串主动驻留
给动态属性赋值前,调用string.Intern()将字符串加入全局驻留池,保证属性值和查询里的字面量引用一致,代码示例:
注意该方案会增加长期内存占用,仅适合字段值重复度高、总数据量不大的场景。string safeValue = field.Value?.ToString() ?? string.Empty; dynamicClass.SetDynamicPropertyValue<string>(field.Name, string.Intern(safeValue)); - 替换适配动态结构的其他实现
如果不想修改现有查询逻辑,可以选择以下替代方案承载动态数据,实现无异常的表达式过滤:- 升级到最新版Dynamic Linq,新版本已经修复了动态生成类型字符串默认走引用比较的已知问题
- 使用JSON动态类型承载动态字段,这类类型的属性默认按值比较,配合常规Linq能力就可以直接实现字符串条件过滤
- 根据字段元数据手动构建表达式树,生成强类型的相等比较逻辑,完全规避动态解析的默认行为问题
内容的提问来源于stack exchange,提问作者AnC Dev
相关产品推荐
相关产品推荐

