目标是从两个 LambdaExpression 获取 MemberExpressions 数组。第一个可转换为返回对象实例的 MethodCallExpression (Expression>
)。第二个 Lambda 表达式将获取第一个表达式的编译结果并返回嵌套成员 (Expression>
)。我们可以假设第二个 Lambda 表达式只会调用嵌套属性,但可能会执行其中多个调用。
因此,我尝试创建的方法的签名是:
MemberExpression[] GetMemberExpressionArray(Expression> instanceExpression, Expression>nestedMemberExpression)< /code>
其中 nestedMemberExpression
将被假定采用
parent =>; 形式的参数Parent.ChildProperty.GrandChildProperty
和结果数组表示从 parent
到 ChildProperty
以及从 ChildProperty
的值到 的 MemberAccess >GrandChildProperty
。
我已经使用以下扩展方法返回了最后一个 MemberExpression
。
public static MemberExpression GetMemberExpression<T, TValue>(Expression<Func<T, TValue>> expression)
{
if (expression == null)
{
return null;
}
if (expression.Body is MemberExpression)
{
return (MemberExpression)expression.Body;
}
if (expression.Body is UnaryExpression)
{
var operand = ((UnaryExpression)expression.Body).Operand;
if (operand is MemberExpression)
{
return (MemberExpression)operand;
}
if (operand is MethodCallExpression)
{
return ((MethodCallExpression)operand).Object as MemberExpression;
}
}
return null;
}
现在,我知道有几种方法可以实现这一目标。对我来说最直接直观的是循环遍历 .Expression
属性来获取第一个表达式并捕获对每个 MemberExpression 的引用。这可能是最好的方法,但也可能不是。我不太熟悉使用这样的表达式所带来的性能成本。我知道 MemberExpression 有一个 MemberInfo 并且该反射应该会损害性能。
我尝试搜索有关表达式的信息,但我所找到的资源非常有限。
对于如何以最佳性能和可靠性完成此任务(以及一般情况下此类任务)的任何建议,我将不胜感激。
The objective is to get an array of MemberExpressions from two LambdaExpressions. The first is convertible to a MethodCallExpression that returns the instance of an object (Expression<Func<T>>
). The second Lambda expression would take the result of the compiled first expression and return a nested member (Expression<Func<T,TMember>>
). We can assume that the second Lambda expression will only make calls to nested properties, but may do several of these calls.
So, the signature of the method I am trying to create is :
MemberExpression[] GetMemberExpressionArray<T,TValue>(Expression<Func<T>> instanceExpression, Expression<Func<T,TValue>> nestedMemberExpression)
where nestedMemberExpression
will be assumed to take an argument of the form
parent => parent.ChildProperty.GrandChildProperty
and the resulting array represents the MemberAccess from parent
to ChildProperty
and from the value of ChildProperty
to GrandChildProperty
.
I have already returned the last MemberExpression
using the following extension method.
public static MemberExpression GetMemberExpression<T, TValue>(Expression<Func<T, TValue>> expression)
{
if (expression == null)
{
return null;
}
if (expression.Body is MemberExpression)
{
return (MemberExpression)expression.Body;
}
if (expression.Body is UnaryExpression)
{
var operand = ((UnaryExpression)expression.Body).Operand;
if (operand is MemberExpression)
{
return (MemberExpression)operand;
}
if (operand is MethodCallExpression)
{
return ((MethodCallExpression)operand).Object as MemberExpression;
}
}
return null;
}
Now, I know there are several ways to accomplish this. The most immediately intuitive to me would be to loop through the .Expression
property to get the first expression and capture references to each MemberExpression along the way. This may be the best way to do it, but it may not. I am not extraordinarily familiar with the performance costs I get from using expressions like this. I know a MemberExpression has a MemberInfo and that reflection is supposed to hurt performance.
I've tried to search for information on expressions, but my resources have been very limited in what I've found.
I would appreciate any advice on how to accomplish this task (and this type of task, in general) with optimal performance and reliability.
发布评论
评论(1)
我不确定为什么它被标记为性能,但我能想到的从树中提取成员表达式的最简单方法是子类化
ExpressionVisitor
。这应该比手动编写逻辑来“扩展”不同类型的表达式并遍历树要简单得多。您可能必须覆盖
VisitMember
方法以便:我想这看起来像:
我对你剩下的任务有点不清楚;看起来您想要重写参数表达式,在这种情况下您可能需要查看此答案来自 Marc Gravell。
I'm not sure why this has been tagged performance, but the easiest way I can think of to extract member-expressions from a tree is to subclass
ExpressionVisitor
. This should be much simpler than manually writing the logic to 'expand' different types of expressions and walk the tree.You'll probably have to override the
VisitMember
method so that:I imagine that would look something like:
I'm slightly unclear about the remainder of your task; it appears like you want to rewrite parameter-expressions, in which case you might want to look at this answer from Marc Gravell.