gpt4 book ai didi

c# - 我有一个带有词法分析器、解析器和求值器的自定义表达式程序。我如何对其进行 LINQ 化?

转载 作者:太空狗 更新时间:2023-10-30 01:23:17 25 4
gpt4 key购买 nike

这是我的接口(interface)和枚举,稍微简化了一些。 :

public interface IExpression
{
ExpressionType ExpressionType { get; }
}

public interface ILiteralExpression : IExpression
{
object Value { get; set; }
}

public interface IOperatorExpression : IExpression
{
IExpression[] Operands { get; set; }

string OperatorUniqueName { get; set; }

IOperatorExpression SetOperand(int index, IExpression expression);
}

public enum ExpressionType
{
Operator,
Literal
}

要创建一个表达式,我可以这样做:

var expression = ExpressionManager.Engines["Default"].Parser.Parse("1 + 3 * 4 + \"myVariable\"");

相当于这样的东西:

var expression1 = ExpressionManager.CreateOperator("Add", 2).
SetOperand(0, ExpressionManager.CreateOperator("Add", 2).
SetOperand(0, ExpressionManager.CreateLiteral(1)).
SetOperand(1, ExpressionManager.CreateOperator("Multiply", 2).
SetOperand(0, ExpressionManager.CreateLiteral(3)).
SetOperand(1, ExpressionManager.CreateLiteral(4)))).
SetOperand(1, ExpressionManager.CreateLiteral("myVariable"));

我希望能够(高效地)做这样的事情:

(from e in expression
where e is ILiteralExpression && "myVariable".Equals(((ILiteralExpression)e).Value)
select (ILiteralExpression)e).ToList().
ForEach(e => e.Value = 2);

我想我需要执行一些 IQueryable 或其他操作,但我不确定从哪里开始。有什么建议吗?

最佳答案

遍历表达式树,将每个元素转换为 System.Linq.Expressions 中的一个对象命名空间,使用 Expression 的工厂方法类。

如果您无法修改您的 IExpression类来添加让您实现 visitor pattern 的方法,你可以依靠旧样式的类型检查:

private static Expression ConvertExpression(IExpression expr) {
if (expr is ILiteralExpression) {
return Expression.Constant(((ILiteralExpression)expr).Value);
}
if (expr is IOperatorExpression) {
var ops = ((IOperatorExpression)expr)
.Operands
.Select(ConvertExpression)
.ToList();
var res = ops[0];
for (int i = 1 ; i != ops.Length ; i++) {
if (((IOperatorExpression)expr).OperatorUniqueName == "+") {
res = Expressions.Add(res, ops[i]);
} else if (((IOperatorExpression)expr).OperatorUniqueName == "-") {
res = Expressions.Subtract(res, ops[i]);
} else if (...) {
}
}
return res;
}
}

当然,您在此方法中需要更多逻辑。关键部分是传递参数:你需要弄清楚你的变量在哪里以及它们的类型是什么,使用 Expression.ParameterExpression创建它,然后将转换后的表达式编译成 Func<...>某种使用 LambdaExpression.Compile 方法。有了已编译的 lambda,您可以将表达式插入到 LINQ 的内存框架中。

如果你能使你的IExpressions visitable,添加一个遍历表达式并使用堆栈将其转换为 LINQ 表达式的访问者。

关于c# - 我有一个带有词法分析器、解析器和求值器的自定义表达式程序。我如何对其进行 LINQ 化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11613842/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com