我试着像这样编写动态 linq:
public struct MyStruct
{
public string name;
public List<string> list;
}
void sth()
{
List<string> _aim = new List<string>();
List<MyStruct> _source = new List<MyStruct>();
_source.Where(it => _aim.Contains(it.name));
}
但是我对带参数的contains方法有问题。任何人都知道如何以简单和通用的方式做到这一点? 通过功能链接:
public static IQuerable<T> Sths(this IQuerable<T> source, IQuerable<string> aim, string columnName)
其中name在columnName中,source是通用的,aim是字符串列表。
答案 0 :(得分:0)
为此,我们可以编写一个表达式,该表达式将属性的值作为参数,并使用它来执行Contains
检查,作为构建该部分的一个简单方法。表达。之后,我们可以用表达式替换该表达式主体中的参数,该表达式从表示源中项目的参数访问属性值,然后使用该主体构建lambda。
public static IQueryable<T> ProjectionIsIn<T>(
this IQueryable<T> source,
IQueryable<string> collection,
string columnName)
{
var param = Expression.Parameter(typeof(T));
Expression<Func<string, bool>> containsExpression =
s => collection.Contains(s);
var predicateBody = containsExpression.Body.Replace(
containsExpression.Parameters[0],
Expression.Property(param, columnName));
Expression<Func<T, bool>> predicate =
Expression.Lambda<Func<T, bool>>(predicateBody, param);
return source.Where(predicate);
}
以下方法用于将一个表达式的所有实例替换为另一个:
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);
}
}