如何提取表达式的一部分
本文关键字:表达式 一部分 提取 何提取 | 更新日期: 2023-09-27 18:16:08
我想简化代码来添加关联过滤,所以我创建了这个类。
class GraphQuery<T>
{
private IQueryable<T> query;
private DataLoadOptions load;
public GraphQuery(DataLoadOptions load, IQueryable<T> query)
{
this.load = load;
this.query = query;
}
public GraphQuery<T> Load(
Expression<Func<T, object>> expr,
Expression<Func<T, object>> filter)
{
load.LoadWith(expr);
load.AssociateWith(filter);
return this;
}
// more public methods ...
}
可以这样使用:
var clients = Graph(db.Clients.Where(e => !e.Deleted))
.Load(e => e.ClientPersons,
e => e.ClientPersons.Where(j => !j.Person.Deleted));
然而,我看到了e => e.ClientPersons
的一个非常简单的重复。所以我想把上面的用法减少到:
var clients = Graph(db.Clients.Where(e => !e.Deleted))
.Load(e => e.ClientPersons.Where(j => !j.Person.Deleted));
那么Load函数应该看起来像
public GraphQuery<T> Load(Expression<Func<T, object>> filter)
{
var expr = ... extract first part of the expression that represents the association property
load.LoadWith(expr);
load.AssociateWith(filter);
return this;
}
我从来没有使用过linq表达式,除了在查询
我使用调试器查看可以从表达式中得到什么,发现提取所需内容相当简单。我猜它不漂亮,但它完成了工作。如果有人有什么建议,请发表评论。
private static LambdaExpression GetRootMemberExpression(LambdaExpression lambda1)
{
var expr = lambda1.Body;
while (!FindRoot(ref expr)) ;
if (!(expr is MemberExpression))
throw new Exception("MemberExpression required");
return Expression.Lambda(expr, (expr as MemberExpression).Expression as ParameterExpression);
}
private static bool FindRoot(ref Expression expr)
{
if (expr is MemberExpression)
return FindRoot(ref expr, (expr as MemberExpression).Expression);
if (expr.NodeType == ExpressionType.Call)
return FindRoot(ref expr, (expr as MethodCallExpression).Object);
throw new Exception("Unexpected Expression type encountered (" + expr.NodeType + ")");
}
private static bool FindRoot(ref Expression expr, Expression expr2)
{
if (expr2.NodeType == ExpressionType.Parameter)
return true;
expr = expr2;
return false;
}