gpt4 book ai didi

c# - 如何将表达式编译成实际结果?

转载 作者:太空狗 更新时间:2023-10-29 23:53:34 25 4
gpt4 key购买 nike

我正在使用表达式围绕 Web 服务调用构建 API,以允许开发人员指定查询并让 ExpressionVisitor 将表达式转换为查询字符串。该请求是 XML,其中包含一个包含查询字符串的特定元素。

例如,我可以做这样的事情来检索银行名称为银行 1 或银行 2 的所有支票账户:

“bankname = 'Bank 1' or bankname = 'Bank 2'”

Web 服务可以处理复杂得多的查询,但我现在就坚持使用它。

所以我有一个 CheckingAccount 类:


[IntacctObject("checkingaccount")]
public class CheckingAccount : Entity
{
[IntacctElement("bankaccountid")]
public string Id { get; set; }

[IntacctElement("bankname")]
public string BankName { get; set; }
}

还有一个 ExpressionVisitor,其主要功能是转换这样的表达式:

Expression> expression = ca => ca.BankName == "Bank 1" || ca.BankName == "Bank 2"

into the query: "bankname = 'Bank 1' or bankname = 'Bank 2'"

This isn't so tough. Where things start to break down are when I introduce local variables:


var account = new CheckingAccount { BankName = "Bank 1" };
string bankName = "Bank 2";

Expression> expression = ca => ca.BankName == account.BankName || ca.BankName == bankName;

我知道如何处理一个简单的局部变量(即 string bankName = "Bank 2"),但处理另一个类型(var account = new CheckingAccount { BankName = "Bank 1"})要复杂得多.

归根结底,这些是我现在需要弄清楚如何处理的大问题。我知道还有更复杂的情况,但我目前并不那么关心这些。

这是我的表达式访问者(请注意方法 CreateFilter 的通用约束):


internal class IntacctWebService30ExpressionVisitor : ExpressionVisitor
{
private readonly List _Filters = new List();
private IntacctWebServicev30SimpleQueryFilter _CurrentSimpleFilter;
private IntacctWebServicev30ComplexQueryFilter _CurrentComplexFilter;
private MemberExpression _CurrentMemberExpression;

public string CreateFilter(Expression> expression) where TEntity : Entity
{

Visit(expression);

string filter = string.Join(string.Empty, _Filters.Select(f => f.ToString()).ToArray());
return filter;
}

protected override Expression VisitBinary(BinaryExpression node)
{
switch (node.NodeType)
{
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
_CurrentComplexFilter = new IntacctWebServicev30ComplexQueryFilter { ExpressionType = node.NodeType };
break;
case ExpressionType.Equal:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.NotEqual:
_CurrentSimpleFilter = new IntacctWebServicev30SimpleQueryFilter { ExpressionType = node.NodeType };
break;
}

return base.VisitBinary(node);
}

protected override Expression VisitMember(MemberExpression node)
{
var attr = node.Member.GetAttribute();
if (attr != null)
_CurrentSimpleFilter.FieldName = attr.FieldName;
else
_CurrentMemberExpression = node;

return base.VisitMember(node);
}

protected override Expression VisitConstant(ConstantExpression node)
{
object value = Expression.Lambda>(node).Compile().Invoke();

string fieldValue = extraxtFieldValue(value, node);

_CurrentSimpleFilter.FieldValue = fieldValue;

if (_CurrentComplexFilter != null)
{
if (_CurrentComplexFilter.Left == null)
{
_CurrentComplexFilter.Left = _CurrentSimpleFilter;
}
else if (_CurrentComplexFilter.Right == null)
{
_CurrentComplexFilter.Right = _CurrentSimpleFilter;
_Filters.Add(_CurrentComplexFilter);
}
else
throw new InvalidOperationException();
}
else
{
_Filters.Add(_CurrentSimpleFilter);
}

return base.VisitConstant(node);
}

private string extraxtFieldValue(object value)
{
string fieldValue;
if (value is DateTime)
fieldValue = ((DateTime)value).ToString("yyyy-MM-dd");
else if (value is string)
fieldValue = value.ToString();
else if (value.GetType().IsEnum)
{
throw new NotImplementedException();
}
else
{
// Not sure if this is the best way to do this or not but can't figure out how
// else to get a variable value.

// If we are here then we are dealing with a property, field, or variable.
// This means we must extract the value from the object.
// In order to do this we will rely on _CurrentMemberExpression
if (_CurrentMemberExpression.Member.MemberType == MemberTypes.Property)
{
fieldValue = value.GetType().GetProperty(_CurrentMemberExpression.Member.Name).GetValue(value, null).ToString();
}
else if (_CurrentMemberExpression.Member.MemberType == MemberTypes.Field)
{
fieldValue = value.GetType().GetFields().First().GetValue(value).ToString();
}
else
{
throw new InvalidOperationException();
}
}

return fieldValue;
}
}

如果您需要更多详细信息,请告诉我....

谢谢

最佳答案

看看an article about this very issue from Matt Warren .他为执行此操作的类提供了源代码,并解释了它是如何做到的。它也包含在 his IQToolkit 中.

关于c# - 如何将表达式编译成实际结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7000820/

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