我对以下任务感到困惑:
假设我有一个包含名称和值的列表(如词典)。我需要为Web界面的用户提供一个可以编写查询的字段,检查该列表中是否存在特定的名称和值。
例如,我有以下列表:
A = 2, B = 4, D = 0
用户希望像这样查询此列表(不要介意语法,它只是一个伪代码)
A == 2 && D
=>这将返回true
,因为A
存在且其值为2
且D
也存在。(A && B) || C
=>这会返回true
,因为列表中存在A
和B
。A && !B
=>这会返回false
,因为A
存在于列表中,但B
也是如此(但B
不应该我一直在寻找动态LINQ
,但似乎我一次只能评估一个对象(无法检查列表中是否存在对象,然后询问是否存在另一个对象没有按' T)。
有谁知道任何有用的材料或链接?
感谢
答案 0 :(得分:3)
不确定我是否了解您的要求......
这就是你要求的吗?
Dictionary<string, int> nameValuePairs = new Dictionary<string, int>();
nameValuePairs.Add("A", 2);
nameValuePairs.Add("B", 4);
nameValuePairs.Add("D", 0);
//A == 2 && D => this returns true, as A exists and it's value is 2 and D also exists
int d = 0;
if (nameValuePairs.ContainsKey("A") && nameValuePairs.TryGetValue("D", out d) && nameValuePairs.ContainsKey("D"))
{
Console.WriteLine("Test 1: True");
}
else
{
Console.WriteLine("Test 1: False");
}
//(A && B) OR C => this returns true, as both A and B exists on the list
if ((nameValuePairs.ContainsKey("A") && nameValuePairs.ContainsKey("B")) || nameValuePairs.ContainsKey("C"))
{
Console.WriteLine("Test 2: True");
}
else
{
Console.WriteLine("Test 2: False");
}
//A && !B => this returns false, as A exists on the list but B as well (but B shouldn't)
if (nameValuePairs.ContainsKey("A") && !nameValuePairs.ContainsKey("B"))
{
Console.WriteLine("Test 3: True");
}
else
{
Console.WriteLine("Test 3: False");
}
答案 1 :(得分:0)
主要想法 - 您将创建动态代码(查看GenerateCode
函数),就像字符串一样(它将与您的表达式类似)然后编译它组装。然后通过反射,您将采用特定方法Calculate
并执行它。我创建了Wrapper
类(字典和数字中的每个项目都将包含在其中),因为像&#34;&amp;&#34;和&#34; |&#34; int
类型无法实现。
注意:取代&#34;&amp;&amp;&#34;,&#34; OR&#34;你应该使用&#34;&amp;&#34;,&#34; |&#34;在计算之前从客户端检索后更换或替换它们。
<强>代码:强>
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication5
{
public class Program
{
public static string GenerateCode(Dictionary<string, int> dict, string expres)
{
var r = new Regex(@"-?\d+");
foreach (var item1 in r.Matches(expres))
expres = expres.Replace(item1.ToString(), string.Format("(new Wrapper({0}))", item1.ToString()));
r = new Regex("[A-Z]");
var res = "";
var areadyDone = new List<string>();
foreach (var item in r.Matches(expres))
{
var key = item.ToString();
if (!areadyDone.Contains(key))
{
res += string.Format("var {0} = new Wrapper({1});\n", item, dict.ContainsKey(key) ? dict[key].ToString() : "");
areadyDone.Add(key);
}
}
return string.Format("{0}return {1};", res, expres);
}
public static bool GetAnswer(Dictionary<string, int> dict, string expres)
{
string code = @"
using System;
namespace First
{
public class Wrapper
{
public int value;
public bool exist = false;
public Wrapper(int value)
{
this.value = value;
this.exist = true;
}
public Wrapper()
{
}
private static bool wrap(Wrapper c1, Wrapper c2, bool cond)
{
return (c1 & c2) ? cond : false;
}
public static bool operator &(Wrapper c1, Wrapper c2)
{
return c1.exist && c2.exist;
}
public static bool operator |(Wrapper c1, Wrapper c2)
{
return c1.exist || c2.exist;
}
public static bool operator !(Wrapper c1)
{
return !c1.exist;
}
public static implicit operator bool(Wrapper d)
{
return d.exist;
}
public static bool operator >(Wrapper c1, Wrapper c2)
{
return wrap(c1, c2, c1.value > c2.value);
}
public static bool operator <(Wrapper c1, Wrapper c2)
{
return wrap(c1, c2, c1.value < c2.value);
}
public static bool operator >=(Wrapper c1, Wrapper c2)
{
return wrap(c1, c2, c1.value >= c2.value);
}
public static bool operator <=(Wrapper c1, Wrapper c2)
{
return wrap(c1, c2, c1.value <= c2.value);
}
public static bool operator ==(Wrapper c1, Wrapper c2)
{
return wrap(c1, c2, c1.value == c2.value);
}
public static bool operator !=(Wrapper c1, Wrapper c2)
{
return wrap(c1, c2, c1.value != c2.value);
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
public class Program
{
public static bool Calculate()
{
" + GenerateCode(dict, expres) + @"
}
public static void Main()
{
}
}
}";
var provider = new CSharpCodeProvider();
var parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = true;
var results = provider.CompileAssemblyFromSource(parameters, code);
if (results.Errors.HasErrors)
{
var sb = new StringBuilder();
foreach (CompilerError error in results.Errors)
sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
throw new InvalidOperationException(sb.ToString());
}
else
{
var assembly = results.CompiledAssembly;
var program = assembly.GetType("First.Program");
var main = program.GetMethod("Calculate");
return (bool)main.Invoke(null, null);
}
}
public static void Main()
{
var dict = new Dictionary<string, int>();
dict.Add("A", 23);
dict.Add("B", 4);
dict.Add("F", 5);
Console.WriteLine(GetAnswer(dict, "(C > -5) | (A >= 10 & B)"));
}
}
}
答案 2 :(得分:0)
好吧,实际上Heinzi回答了我的问题,指出有一个问题可以回答我的问题:How to parse a boolean expression and load it into a class?
我已经复制了那里提供的代码并且它完美无瑕。没有动态代码(对我来说太难了),简单的二叉树。
谢谢大家的参与。