使用DynamicExpressionParser解析Lambda的Select方法报错,如何解决?
解决DynamicExpressionParser解析Select方法的问题
我正在使用DynamicExpressionParser,但需要解析Select方法,以下是我的代码:
using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Text.RegularExpressions; var categories = new List<Dictionary<string, object>> { new() {{"id", 1}, {"name", "Food"}}, new() {{"id", 2}, {"name", "Drink"}}, new() {{"id", 3}, {"name", "Snack"}} }; var dict = new Dictionary<string, object> {{"categories", categories}}; // var codeToGetFirstCategoryName = "Category Name: ${categories[0][\"name\"]}"; // This is working var codeToGetNames = "Category Names: ${string.Join(\"\", categories.Select(x => x[\"name\"]))}"; var result = StringHelper.Interpolate(codeToGetNames, dict); Console.WriteLine(result); public static class StringHelper { public static string Interpolate(string text, Dictionary<string, object> row, string pattern = @"\$\{(?:<key>[^{}]*)}") { return Regex.Replace(text, pattern, match => { var parameterExpressions = row.Select(column => Expression.Parameter(column.Value.GetType(), column.Key)); var lambdaExpression = DynamicExpressionParser.ParseLambda(parameterExpressions.ToArray(), typeof(object), match.Groups["key"].Value, row.Values.ToArray()); return lambdaExpression.Compile().DynamicInvoke(row.Values.ToArray())?.ToString() ?? string.Empty; }); } }
运行时抛出异常:
Unhandled exception. ')' or ',' expected (at index 38)
问题原因及修复方案
1. 正则表达式命名组错误
原正则中的<key>不是合法的命名组语法,无法正确提取${}内的表达式内容,需改为(?<key>[^{}]*)。
2. 动态表达式语法适配
DynamicExpressionParser的语法与原生C#有细微差异,同时需确保字符串转义正确。修正后的代码如下:
using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Text.RegularExpressions; var categories = new List<Dictionary<string, object>> { new() {{"id", 1}, {"name", "Food"}}, new() {{"id", 2}, {"name", "Drink"}}, new() {{"id", 3}, {"name", "Snack"}} }; var dict = new Dictionary<string, object> {{"categories", categories}}; var codeToGetNames = "Category Names: ${string.Join(\", \", categories.Select(x => x[\"name\"]))}"; var result = StringHelper.Interpolate(codeToGetNames, dict); Console.WriteLine(result); public static class StringHelper { public static string Interpolate(string text, Dictionary<string, object> row, string pattern = @"\$\{(?<key>[^{}]*)}") { return Regex.Replace(text, pattern, match => { var parameterExpressions = row.Select(column => Expression.Parameter(column.Value.GetType(), column.Key)).ToArray(); var expressionText = match.Groups["key"].Value; var lambdaExpression = DynamicExpressionParser.ParseLambda(parameterExpressions, typeof(object), expressionText); var compiled = lambdaExpression.Compile(); return compiled.DynamicInvoke(row.Values.ToArray())?.ToString() ?? string.Empty; }); } }
替代方案:使用Roslyn脚本引擎
如果DynamicExpressionParser的语法限制无法满足需求,可以改用Roslyn脚本引擎,它支持完整的C#语法:
using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; using System.Text.RegularExpressions; var categories = new List<Dictionary<string, object>> { new() {{"id", 1}, {"name", "Food"}}, new() {{"id", 2}, {"name", "Drink"}}, new() {{"id", 3}, {"name", "Snack"}} }; var dict = new Dictionary<string, object> {{"categories", categories}}; var codeToGetNames = "Category Names: ${string.Join(\", \", categories.Select(x => x[\"name\"]))}"; var result = StringHelper.Interpolate(codeToGetNames, dict); Console.WriteLine(result); public static class StringHelper { public static string Interpolate(string text, Dictionary<string, object> row, string pattern = @"\$\{(?<key>[^{}]*)}") { var options = ScriptOptions.Default.WithImports("System", "System.Linq", "System.Collections.Generic"); return Regex.Replace(text, pattern, async match => { var expressionText = match.Groups["key"].Value; var script = CSharpScript.Create<object>(expressionText, options, typeof(Dictionary<string, object>)); var result = await script.RunAsync(row); return result.ReturnValue?.ToString() ?? string.Empty; }).Result; } }
使用此方案需要安装NuGet包Microsoft.CodeAnalysis.CSharp.Scripting。
内容的提问来源于stack exchange,提问作者AliRıza Adıyahşi
相关产品推荐
相关产品推荐

