我需要一种将选择器表达式转换为谓词表达式的方法,以便将其连同一些参数传递给查询提供程序。
private Expression<Func<T, TKey>> PrimaryKeySelector { get; set; }
private ISpecification<T> GetByPrimaryKeySpecification(TKey key) {
lambda = ... // some magic, also unicorns
return new ExpressionSpecification(lambda);
}在第一次尝试中,我使用Expression.Equal构建了谓词表达式,但是这给分析表达式的查询提供程序带来了问题(例如,NHibernate由于未知的Equal语句而失败)。另外,我看到了创建新ParameterExpression并通过调用选择器表达式使用选择器表达式的结果的解决方案,但是我觉得这很糟糕,因为1)性能和2)参数表达式已经包含在选择器表达式中。
有什么建议吗?
发布于 2014-09-24 14:09:20
你在这里要做的是用另一个表达式组成一个表达式。使用函数进行此操作非常容易;使用表达式进行此操作需要做更多的工作。
您可以做的是将参数的所有实例替换为第二个表达式,谓词,使用第一个函数的主体,选择器。
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}这依赖于以下方法将一个表达式的所有实例替换为另一个表达式:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal 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 node)
{
return node == from ? to : base.Visit(node);
}
}最后一个缺失的谜题是,您将无法使用==运算符在泛型方法中比较您的值,因为您无法确定类型超越了==运算符;您需要手动构建相等的表达式:
public static Expression<Func<T, bool>> EqualsValue<T>(T value)
{
var param = Expression.Parameter(typeof(T));
var body = Expression.Equal(param, Expression.Constant(value));
return Expression.Lambda<Func<T, bool>>(body, param);
}这使您可以编写:
return PrimaryKeySelector.Compose(EqualsValue(key));至于你对表现的担忧,不要担心。构建像这样的表达式树所花费的时间将比您将使用它们进行的网络请求慢很多数量级。在表达式操作上花费一些额外的时间甚至不会对应用程序的性能产生可衡量的影响;它将大大低于网络请求的噪音。
https://stackoverflow.com/questions/26018685
复制相似问题