我正在使用一个小型库,在运行时生成'where'表达式。我已经能够使用Expression.Equal
,Expression.NotEqual
等不同的运算符导航对象属性和查询,甚至可以在字符串上使用.Contains()
方法。
我遇到过需要创建表示链式方法的表达式的情况,如:x => x.SomeColumn.Trim().EndsWith("SomeText")
。我不知道从哪里开始。
我已经像这样实现了.EndsWith()
方法:
static Expression<Func<TEntity, bool>> GetEndsWithExpression(
ParameterExpression parameterExpression,
Expression propertyExpression,
Expression valueToFind)
{
var propertyExp = propertyExpression;
var method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
var someValue = valueToFind;
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
return Expression.Lambda<Func<TEntity, bool>>(containsMethodExp, parameterExpression);
}
我想知道您是否可以帮我弄清楚如何添加.Trim()
方法并使用.EndsWith()
方法将其链接起来。
其他一些信息,我已经在我的项目中使用了LINQKit,所以像.AsExpandable()
这样的东西对我来说有些熟悉。
我认为解决方案看起来像这样:
static Expression<Func<TEntity, bool>> GetTrimEndsWithExpression(
ParameterExpression parameterExpression,
Expression propertyExpression,
Expression valueToFind)
{
var propertyExp = propertyExpression;
var trimMethod = typeof(string).GetMethod("Trim");
var endsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
var trimMethodExpression = Expression.Call(propertyExp, trimMethod).Expand();
var containsMethodExp = Expression.Call(trimMethodExpression, endsWithMethod, valueToFind);
return Expression.Lambda<Func<TEntity, bool>>(containsMethodExp, parameterExpression);
}
然而,这无法编译。它抛出一个错误:
System.Reflection.AmbiguousMatchException: Ambiguous match found.
如何在运行时生成的表达式中链接这两个方法?
答案 0 :(得分:5)
处理这个的简单方法是编写一个Compose
方法,允许你在另一个表达式中组合一个表达式,这在一般情况下解决了这个问题:
public static Expression<Func<T, TResult>> Compose<T, TIntermediate, TResult>(
this Expression<Func<T, TIntermediate>> first,
Expression<Func<TIntermedaite, TResult>> second)
{
return Expression.Lambda<Func<T, TResult>>(
second.Body.Replace(second.Parameters[0], first.Body),
first.Parameters[0]);
}
它使用Replace
方法将一个表达式的所有实例替换为另一个表达式,具体定义如下:
public class ReplaceVisitor:ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression ex)
{
if(ex == from) to;
else return base.Visit(ex);
}
}
public static Expression Replace(this Expression ex,
Expression from,
Expression to)
{
return new ReplaceVisitor(from, to).Visit(ex);
}
现在我们有了这个,我们可以编写我们想要的表达式:
public static Expression<Func<TEntity, bool>> EndsWith<TEntity>(
public Expression<Func<TEntity, string>> propertySelector,
string endsWith)
{
return propertySelector.Compose(str => str.Trim().EndsWith(endsWith));
}
答案 1 :(得分:2)
此行正在抛出&#34;发现的模糊匹配&#34;例外:
var trimMethod = typeof(string).GetMethod("Trim");
将其更改为:
var trimMethod = typeof(string).GetMethod("Trim", new Type[0]);