StackOverflow 不是代码编写服务,但有些代码编写起来很有趣。
这是一个将测试短语解析成Expression树然后编译树返回Func来测试HashSet<string>的类:
public static class PhraseCompiler {
public static Regex tokenRE = new Regex(@"\(|\)|&|\||\w+", RegexOptions.Compiled);
static IEnumerable<string> Tokens(string phrase) {
foreach (Match m in tokenRE.Matches(phrase))
yield return m.Value;
}
static MethodInfo HSContainsMI = typeof(HashSet<string>).GetMethod("Contains");
static Expression subCompile(IEnumerator<string> te, ParameterExpression g) {
var stack = new Stack<Expression>();
while (te.MoveNext()) {
switch (te.Current) {
case "(":
break;
case ")":
goto exit_while;
case "|":
case "&":
var op = te.Current;
var lhs = stack.Pop();
var rhs = subCompile(te, g);
var opExpr = Expression.MakeBinary(op == "|" ? ExpressionType.OrElse : ExpressionType.AndAlso, lhs, rhs);
stack.Push(opExpr);
break;
default:
var v = Expression.Constant(te.Current, typeof(string));
var test = Expression.Call(g, HSContainsMI, v);
stack.Push(test);
break;
}
}
exit_while:
return stack.Pop();
}
public static Func<HashSet<string>, bool> Compile(string phrase) {
var g = Expression.Parameter(typeof(HashSet<string>), "g");
var te = Tokens(phrase).GetEnumerator();
var e = subCompile(te, g);
var ef = Expression.Lambda<Func<HashSet<string>, bool>>(e, g);
return ef.Compile();
}
}
给定你的初始值
var A = "ab1, eb4, gr3";
var B = "((ut2 | eg1) | gr3) & ab1";
var C = "ke2 & pa5";
然后你可以将测试值转换为HashSet<string>:
var As = A.Split(", ").ToHashSet();
然后你就可以编译测试了:
var fB = PhraseCompiler.Compile(B);
var fC = PhraseCompiler.Compile(C);
并运行测试:
var testBresult = fB(As);
var testCresult = fC(As);
注意:编译器不会进行错误检查,并且可能会针对错误的测试短语抛出异常。