0

I want to use string predicate instead of lambda code.

Here is list of dictionary:

void GenerateData()
{
    DataDictionary = new List<Dictionary<string, string>>()
    {
        new Dictionary<string, string>()
        {
            {"a","1-1" },
            {"b","1-2" }
        },
        new Dictionary<string, string>()
        {
            {"a","1-3" },
            {"b","1-4" }
        }
    };
}

And find "1-1" from "a"

var data = DataDictionary.AsQueryable();

var result = data.Where(d => d["a"] == "1-1");

Can i convert d => d["a"] == "1-1" to string context? like "d => d[\"a\"] == \"1-1\""

Finally, I want use like this.

ProcessContext("a", "==\"1-1\"")
ProcessContext("a", "!=\"1-1\"")

void ProcessContext(string Field, string Context)
{
    string predicate = $"d => d[\"{Field}\"] {Context}"
    var result = data.Where(predicate);
}

Can someone help me? Thank you very much.

Update

I tried Orace's link How to convert a String to its equivalent LINQ Expression Tree?

It looks perfect solution. But I got an error. I will try to solve.

//Prev - It works
var result1 = data.Where(d => d["a"] == "1-1");

//Use Dynamic linq - 'Syntax error'
var result2 = data.Where("d => d[\"a\"] == \"1-1\"");
YS R
  • 55
  • 9
  • Not related to your question, but if `DataDictionary` is a `List>`, why call `AsQueryable()`? – Laurent Gabiot Jun 02 '22 at 06:19
  • Can you explain why `Func>> getResult = (k, v) => DataDictionary.Where(d => d[k] == v);` wouldn't be useful for you? – Enigmativity Jun 02 '22 at 06:33
  • How does `void ProcessContext(string Field, string Context)` help you? What problem have you got that this solves? – Enigmativity Jun 02 '22 at 06:39
  • I also want `DataDictionary.Where(d => d[k] != v);` I think my post is not cleared. Edit for this – YS R Jun 02 '22 at 06:40
  • @YSR - Can you explain why `Func>> getResult = (k, b, v) => DataDictionary.Where(d => b ? d[k] == v : d[k] != v);` wouldn't be useful for you? – Enigmativity Jun 02 '22 at 06:42
  • I want dynamic context. Like `a==1` `a < 10` `a != "a"` `(a==1) && (b<10)` – YS R Jun 02 '22 at 06:45
  • Does this answer your question? [How to convert a String to its equivalent LINQ Expression Tree?](https://stackoverflow.com/questions/821365/how-to-convert-a-string-to-its-equivalent-linq-expression-tree) – Orace Jun 02 '22 at 06:47
  • @YSR - Yes, I understand that. But why? Why do you need it? And what problem do you solve with it? How does it surface to the end user? – Enigmativity Jun 02 '22 at 06:52
  • @YSR - You have to somehow build these dynamic strings. How are you doing that? – Enigmativity Jun 02 '22 at 06:53
  • @Enigmativity - I will provide customizable search funtion from parsed dataset for end user. – YS R Jun 02 '22 at 07:37
  • @YSR - So you're presenting the strings `"==\"1-1\""` and `"!=\"1-1\""` (as an example) for the user to select? It seems to me that a `Dictionary` could give you a more user friendly approach without resorting to dynamic predicates. – Enigmativity Jun 02 '22 at 07:40
  • @Enigmativity - User can type any Context string. And Dictionary for what? – YS R Jun 02 '22 at 07:48
  • You can create dictionaries of delegates with strings as keys. You present the keys to the users and you execute the delegates without resorting to dynamically generated code. – Enigmativity Jun 02 '22 at 07:57
  • @YSR - Are you saying you want the users to type their own queries? – Enigmativity Jun 02 '22 at 07:57
  • Yes. They need their own queries. – YS R Jun 02 '22 at 07:59
  • @YSR - That doesn't seem at all practical. It seems to me that you could do much better with a simple query builder. – Enigmativity Jun 02 '22 at 08:01
  • Isn't it an injection attack vector ? What about if a user enter some malicious expression ? – Steve B Jun 02 '22 at 09:53

2 Answers2

1

It is possible to create string predicate with Dynamic Linq. Unfortunately, I am not familiar with it enough to tell how to iterate over a nested dictionary, so I use combined approach of a simple predicate $"Key == @0 && Value == @1" and foreach loop. You might want to learn more about this nuget package to get rid of foreach loop.

using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;

namespace DynamicLinqDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var item = GetDictionaryItem();
        }

        public static Dictionary<string, string> GetDictionaryItem()
        {
            var dict = new List<Dictionary<string, string>>()
            {
                new Dictionary<string, string>()
                {
                    {"a","1-1" },
                    {"b","1-2" }
                },
                new Dictionary<string, string>()
                {
                    {"a","1-3" },
                    {"b","1-4" }
                }
            };

            var Field = "a";
            var Context = "1-1";
            string predicate = $"Key == @0 && Value == @1";

            foreach (var item in dict)
            {
                var result = item.AsQueryable().Where(predicate, Field, Context).ToList();

                if (result.Count > 0)
                    return item;
            }

            return null;
        }
    }
}
Yehor Androsov
  • 4,885
  • 2
  • 23
  • 40
-1
ProcessContext(string Field, string Context)
{
        Func<Dictionary<string, string>, bool> p1 = d => d.ContainsKey(Field);
                Func<Dictionary<string, string>, bool> p2 = d => d[Field] == Context;
                Func<Dictionary<string, string>, bool> p3 = d => p1(d) && p2(d);
    var result = data.Where(p3);
}