我试图动态创建表达但我无法弄明白......也不想像这样使用..
if (item.id == 1) filter.AddExpression(c => filterValues.Contains(c.a1));
if (item.id == 2) filter.AddExpression(c => filterValues.Contains(c.a2));
if (item.id == 3) filter.AddExpression(c => filterValues.Contains(c.a3));
if (item.id == 4) filter.AddExpression(c => filterValues.Contains(c.a4));
...
var filtervalues = new List<int>(){1,2,3,4...}
Filter<TestSubject> filter = new Filter<TestSubject>(null);
如何通过迭代来实现这一点...这是一个Web项目和归档ID,它们的值来自IQueryCollection
转换键和值以使用实体框架查询mysql ... for Where
in试图这样做的条款。如果有另一种方式可以欣赏,但现在我有这种强大的方式,但无法完成......
foreach (var field in QueryFields)
{
filter.AddExpression(c => filterValues.Contains(c=>"a"+field.id)); // Trying to do this
}
public class TestSubject
{
public int? a1 { get; set; }
public int? a2 { get; set; }
public int? a3 { get; set; }
public int? a4 { get; set; }
}
public class Filter<TEntity>
{
public Filter(Expression<Func<TEntity, bool>> expression)
{
Expression = expression;
}
public Expression<Func<TEntity, bool>> Expression { get; private set; }
public void AddExpression(Expression<Func<TEntity, bool>> newExpression)
{
if (newExpression == null) throw new ArgumentNullException(nameof(newExpression), $"{nameof(newExpression)} is null.");
if (Expression == null) Expression = newExpression;
var parameter = System.Linq.Expressions.Expression.Parameter(typeof(TEntity));
var leftVisitor = new ReplaceExpressionVisitor(newExpression.Parameters[0], parameter);
var left = leftVisitor.Visit(newExpression.Body);
var rightVisitor = new ReplaceExpressionVisitor(Expression.Parameters[0], parameter);
var right = rightVisitor.Visit(Expression.Body);
Expression = System.Linq.Expressions.Expression.Lambda<Func<TEntity, bool>>(System.Linq.Expressions.Expression.AndAlso(left, right), parameter);
}
}
答案 0 :(得分:1)
假设您处理filterValues
和TestSubject
属性(int
与int?
)之间的类型不匹配,您可以使用辅助函数:
public static Expression<Func<TEntity, bool>> MakeContainsLambda<TEntity, TTest>(Expression<Func<ICollection<TTest>>> valsref, string fieldPrefix, string fieldPostfix) {
var param = Expression.Parameter(typeof(TEntity));
var vals = valsref.Body;
var miContains = valsref.Body.Type.GetMethod("Contains", new[] { typeof(TTest) });
var field = Expression.PropertyOrField(param, fieldPrefix+fieldPostfix);
var body = Expression.Call(vals, miContains, field);
return (Expression<Func<TEntity, bool>>) Expression.Lambda(body, param);
}
创建所需的表达式:
filter.AddExpression(MakeContainsLambda<TestSubject, int>(() => filterValues, "a", item.id.ToString()));
答案 1 :(得分:1)
感谢您的回答是对的,我的结果如下。对于&gt; =并包含过滤器..我用于具有实体框架的查询数据库..
// >=
var parameter = Expression.Parameter(typeof(Cx), "Cx"); // Cx Type.
var member = Expression.Property(parameter, "a" + fieldNo); //Cx.ay
var constant = Expression.Constant(int.Parse(query[fieldNo.ToString()]));
Expression body = Expression.GreaterThanOrEqual(member, Expression.Convert(Expression.Constant(int.Parse(query[.ToString()])), member.Type)); // Contains Conversion for GreaterThanOrEqual not accept int , int?
var finalExpression = Expression.Lambda<Func<Classified, bool>>(body, parameter);
filter.AddExpression(finalExpression);
// Contains
var methodInfo = typeof(List<int?>).GetMethod("Contains", new Type[] { typeof(int?) }); // Contains Method
var parameter = Expression.Parameter(typeof(Cx), "Cx"); // Cx Type.
var member = Expression.Property(parameter, "a" + fieldNo); //Cx.ay
var constant = Expression.Constant(filterValues);
Expression body = Expression.Call(Expression.Constant(filterValues), methodInfo, member);
var finalExpression = Expression.Lambda<Func<Classified, bool>>(body, parameter);
filter.AddExpression(finalExpression);