[英]How to get lambda expression parameters
在我的特定情况下,我动态地构建一个SQL语句来搜索记录。 这发生在WebApi的服务器端,位于业务服务层。 现在,我想扩展此功能,以便也可以在客户端设置WHERE
子句。 我想使用强类型,以便不对客户端上的列名称进行硬编码。
到目前为止,我执行了以下操作:
1)从INFORMATION_SCHEMA
获取视图的列,并填充Dictionary<string, object>
以便在稍后阶段设置列值。 我可能会更改为自定义类,以便可以添加比较器字段,而不是只有column_name = column_value
。
2)我创建了一个自定义属性和一个仅包含要向客户端公开的搜索列的类:
public class CustomerSearchDto
{
[SearchColumn(Name = "customer_type")]
public CustomerType CustomerType { get; set; }
[SearchColumn(Name = "city")]
public string City { get; set; }
public CustomerSearchDto()
{ }
}
3)现在,在客户端中,我可以执行以下操作:
//Following line is pseudo-code
var predicate = (x => x.CustomerType == CustomerType.Private);
如何获取此lambda表达式,并从(1)中获得列列表,并从(2)中获知列名称,设置字典中相应列的值?
有太多的假设,但是您可以从以下内容开始:
static void SetValue<T>(Dictionary<string, object> target, Expression<Func<T, bool>> predicate)
{
var comparison = predicate.Body as BinaryExpression;
Debug.Assert(comparison != null);
var member = (comparison.Left.NodeType == ExpressionType.Convert ?
((UnaryExpression)comparison.Left).Operand :
comparison.Left) as MemberExpression;
Debug.Assert(member != null);
var value = comparison.Right as ConstantExpression;
Debug.Assert(value != null);
var attribute = Attribute.GetCustomAttribute(member.Member, typeof(SearchColumnAttribute)) as SearchColumnAttribute;
var columnName = attribute?.Name ?? member.Member.Name;
var columnValue = value.Value;
target[columnName] = columnValue;
}
测试:
Expression<Func<CustomerSearchDto, bool>> predicate = (x => x.CustomerType == CustomerType.Private);
var dict = new Dictionary<string, object>();
SetValue(dict, predicate);
您可以通过使用ExpressionVisitor
重写客户端,从而一步一步地将客户端表达式从SQL表达式转换为SQL表达式,而不是构建字典然后从中进行查询。
您的ExpressionVisitor
将覆盖适当的方法,例如, protected override Expression VisitMember(MemberExpression node)
,在该方法内部,它将客户端字段名称转换为服务器端字段名称。
仍然存在序列化Expressions客户端并在服务器端反序列化它们的问题,但是一旦有了它们,就可以使用访问者为SQL重写它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.