You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用Newtonsoft.Json.Linq与System.Linq.Dynamic.Core时SelectToken报错问题

解决Dynamic LINQ Core调用JToken.SelectToken时的解析异常问题

我之前也遇到过一模一样的问题,核心原因确实是Dynamic LINQ Core会优先把实现了IEnumerable的类型的方法识别为LINQ聚合/查询运算符,而JToken(包括JObject)正好实现了IEnumerable<JToken>,所以解析器错误地把SelectToken当成了LINQ聚合方法去查找,才抛出了"No applicable aggregate method"异常。

这里有几个比包装类更简洁的解决方案,完全能满足你表达式可存储、可UI配置的需求:

方案1:显式类型转换引导解析器

最简单的办法是在表达式字符串中,把参数显式转换为JToken类型,这样解析器就会优先查找该类型的实例方法,而不是把它当成IEnumerable处理。

修改后的代码示例:

using Newtonsoft.Json.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;

namespace DynamicLinqCore
{
    class Program
    {
        static JObject json = JObject.Parse(@"{}");
        static void Main(string[] args)
        {
            // 通过显式类型转换,让解析器正确识别JToken的实例方法
            var exp = DynamicExpressionParser.ParseLambda(
                new ParameterExpression[] { Expression.Parameter(typeof(JToken), "jobj") }, 
                typeof(JToken), 
                "(jobj as Newtonsoft.Json.Linq.JToken).SelectToken(\"$\")");
            
            // 验证执行效果
            var compiledFunc = exp.Compile();
            var result = compiledFunc.DynamicInvoke(json);
            Console.WriteLine(result?.ToString()); // 输出 {}
        }
    }
}

方案2:配置解析器简化表达式

如果觉得表达式里写完整命名空间太繁琐,可以通过ParsingConfig添加命名空间引用,这样就能用简化的类型名来写表达式:

using Newtonsoft.Json.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Dynamic.Core.Configuration;
using System.Linq.Expressions;

namespace DynamicLinqCore
{
    class Program
    {
        static JObject json = JObject.Parse(@"{}");
        static void Main(string[] args)
        {
            var config = new ParsingConfig
            {
                // 允许通过简单类型名解析类型
                ResolveTypesBySimpleName = true,
                // 添加Newtonsoft.Json.Linq命名空间到解析器的查找范围
                CustomTypeProviders = new[] 
                { 
                    new DefaultDynamicLinqTypeProvider 
                    { 
                        Namespaces = { "Newtonsoft.Json.Linq" } 
                    } 
                }
            };

            var exp = DynamicExpressionParser.ParseLambda(
                config,
                new ParameterExpression[] { Expression.Parameter(typeof(JToken), "jobj") }, 
                typeof(JToken), 
                "(jobj as JToken).SelectToken(\"$\")");
            
            var result = exp.Compile().DynamicInvoke(json);
            Console.WriteLine(result);
        }
    }
}

方案原理说明

Dynamic LINQ的解析逻辑中,当处理成员访问时,如果当前类型实现了IEnumerable,会先尝试匹配LINQ聚合方法;而通过显式类型转换后,解析器会先处理类型转换操作,得到明确的JToken类型,此时就会直接查找该类型的实例方法SelectToken,不会再把它当成LINQ运算符处理。

这两种方案都不需要额外的包装类,同时保持了表达式字符串的可存储性和UI配置友好性,完全符合你的需求。

内容的提问来源于stack exchange,提问作者Magnus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:37:54