如何将形式为的ExpressionTree转换为
Expression<Func<POCO1, bool>> exp = p => p.Age > 50;
转换为
Expression<Func<POCO2, bool>> exp2 = p => p.Age > 50;
POCO1е’ҢPOCO2йғҪжҳҜC#еҜ№иұЎпјҢ并且дёӨиҖ…йғҪжңүInt32зұ»еһӢзҡ„AgeеұһжҖ§гҖӮ
如何将形式为的ExpressionTree转换为
Expression<Func<POCO1, bool>> exp = p => p.Age > 50;
转换为
Expression<Func<POCO2, bool>> exp2 = p => p.Age > 50;
POCO1е’ҢPOCO2йғҪжҳҜC#еҜ№иұЎпјҢ并且дёӨиҖ…йғҪжңүInt32зұ»еһӢзҡ„AgeеұһжҖ§гҖӮ
你可以创建自定义的表达式访问器,来替换参数引用并修补成员访问表达式。
class Converter<TTo>
{
class ConversionVisitor : ExpressionVisitor
{
private readonly ParameterExpression newParameter;
private readonly ParameterExpression oldParameter;
public ConversionVisitor(ParameterExpression newParameter, ParameterExpression oldParameter)
{
this.newParameter = newParameter;
this.oldParameter = oldParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return newParameter; // replace all old param references with new ones
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression != oldParameter) // if instance is not old parameter - do nothing
return base.VisitMember(node);
var newObj = Visit(node.Expression);
var newMember = newParameter.Type.GetMember(node.Member.Name).First();
return Expression.MakeMemberAccess(newObj, newMember);
}
}
public static Expression<Func<TTo, TR>> Convert<TFrom, TR>(
Expression<Func<TFrom, TR>> e
)
{
var oldParameter = e.Parameters[0];
var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name);
var converter = new ConversionVisitor(newParameter, oldParameter);
var newBody = converter.Visit(e.Body);
return Expression.Lambda<Func<TTo, TR>>(newBody, newParameter);
}
}
class A
{
public int Value { get; set; }
}
class B
{
public int Value { get; set; }
}
Expression<Func<A, int>> f = x => x.Value;
var f2 = Converter<B>.Convert(f);
大致步骤:
获取表达式并将其转换为BinaryExpression 获取左操作数并将其转换为MemberExpression 获取属性所属的基础类型 如果可能,将其更改为新类型。
在此处获得的类型是一个没有setter的属性,正如我所猜测的那样。
Expression<Func<MainWindow, bool >> exp1 = o => this.ActualHeight>50;
var type = ((MemberExpression)((BinaryExpression)exp1.Body).Left).Expression.Type;
因此,您必须构建一个新的表达式
以下是方法:
Expression<Func<IPOCO,bool>>
替代一个等效的消耗 lambda 的 POCO1 或 POCO2 - 如果可以的话,就可以完全避开这种复杂性。(不幸的是,问题没有解释这里的动机)。 - Eamon Nerbonne