如何结合Expression< Func< T>和表达式< Func< T,float>.表达式< Func< float> ;? [英] How to combine Expression<Func<T>> and Expression<Func<T,float>> to Expression<Func<float>>?
问题描述
我正在尝试结合 expr1
和 expr2
来生成 Expression< Func< float>>
:
I am trying to combine expr1
and expr2
to produce an Expression<Func<float>>
:
var expr1 = (Expression<Func<ColorComponent>>)(() => _modelRgb.R);
var expr2 = (Expression<Func<ColorComponent, float>>)(s => s.Value);
var expr3 = Expression.Lambda(expr1, expr2.Parameters);
虽然对 expr3
的调用确实起作用,但是其 .Body
属性不能转换为 MemberExpression
.
While the call to expr3
does work, its .Body
property cannot be casted as MemberExpression
.
这是一个手工制作的表达式和 expr3
的调试字符串,显然它们是不同的:
Here are the debug strings of a manually crafted expression and expr3
, obviously they're different:
"() => (ColorPicker.ColorPickerWindow2)._modelRgb.R.Value"
"s => () => (ColorPicker.ColorPickerWindow2)._modelRgb.R"
问题是:
使 expr3
成为 MemberExpression
而不是 LambdaExpression
的正确方法是什么?
What is the correct way to make expr3
a MemberExpression
instead of a LambdaExpression
?
我要实现的目标:
我想传递类似()=>的表达式._modelRgb.R
指向方法的 ColorComponent
,在这种方法中,我想为其成员中的一些成员构建大量表达式.
I'd like to pass expressions like () => _modelRgb.R
that points to a ColorComponent
to a method, and in this method I'd like to build numerous expression to some of its members.
推荐答案
您在这里要做的根本是组成两个表达式.此处是一种显示方法的解决方案,尽管要使第一个表达式没有参数,而不是一个参数,需要一些调整.
What you're fundamentally trying to do here is to compose two expressions. Here is a solution showing how to do that, although it requires a bit of adapdation in order to have the first expression have no parameters, rather than one parameter.
经过修改的 Compose
方法如下所示:
The adapted Compose
method would look like this:
public static Expression<Func<TResult>> Compose<TSource, TResult>(
this Expression<Func<TSource>> first,
Expression<Func<TSource, TResult>> second)
{
return Expression.Lambda<Func<TResult>>(
second.Body.Replace(second.Parameters[0], first.Body));
}
这将使用与链接的问题相同的 Replace
方法,而无需进行任何修改:
This would use the same Replace
method as the linked question, without needing any adaptation:
public class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression ex)
{
if (ex == from) return to;
else return base.Visit(ex);
}
}
public static Expression Replace(this Expression ex,
Expression from,
Expression to)
{
return new ReplaceVisitor(from, to).Visit(ex);
}
通过使用上述方法对代码进行泛化,可以确保代码无论使用哪种表达式都可以正常工作,而不是编写一种对可能存在或不能存在的条件进行假设的方法要么表达,要么以不同的方式处理一堆不同的情况.
By generalizing the code using the above methods you ensure that the code will work regardless of the contents of either expression, rather than writing a method that makes assumptions about what can or can't be in either expression, or to handle a bunch of different cases differently.
这篇关于如何结合Expression< Func< T>和表达式< Func< T,float>.表达式< Func< float> ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!