1

I am using DynamicExpressionParser but I need to parse Select method. Here is the code:

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;
        });
    }
}

This is returning following message:

Unhandled exception. ')' or ',' expected (at index 38)

How I can handle Select? Or completely different solution other than using dynamic expression parser?

Thanks.

AliRıza Adıyahşi
  • 15,658
  • 24
  • 115
  • 197
  • 3
    Just so I understand the question: you're trying to parse the body of a lambda, where the body itself contains a lambda? I'm looking at the documentation for dynamic linq (https://dynamic-linq.net/expression-language) and the lambda operator does not appear to be on the list of supported operators for dynamic expression parsing, which makes sense; I wrote the code to do lambda binding in the C# 3 compiler and it took me almost an entire year of work to get right. There are a lot of subtleties. I would not expect dynamically parsing a lambda from a string to be supported. – Eric Lippert Jul 12 '23 at 18:08
  • I think I should use a template engine or something. – AliRıza Adıyahşi Jul 13 '23 at 01:19

1 Answers1

0

You can use Z.Expressions.Eval package where you can use string.Join and similar methods. The example according to your project codes is arranged below:

public static string Interpolate(string text, Dictionary<string, object> row, string pattern = @"\$\{(?<key>[^{}]*)\}")
    {
        return Regex.Replace(text, pattern, match =>
        {
            //Expression is taken
            var expression = match.Groups["key"].Value;

            //The expression and parameters are sent to the eval method.
            return Eval.Execute<string>(expression, row);
        });
    }

You can check the Z.Expressions.Eval package for the library details.