csharp 在Linq中动态构建Where子句
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 在Linq中动态构建Where子句相关的知识,希望对你有一定的参考价值。
//Build Where Clause Dynamically in Linq
//https://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq
public class Person
{
public string Name { get ; set ; }
public string Surname { get ; set ; }
public int Age { get ; set ; }
public string City { get ; set ; }
public double Salary { get ; set ; }
public bool IsHomeOwner { get ; set ; }
}
public static class ExpressionBuilder
{
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains" );
private static MethodInfo startsWithMethod =
typeof(string).GetMethod("StartsWith", new Type [] {typeof(string)});
private static MethodInfo endsWithMethod =
typeof(string).GetMethod("EndsWith", new Type [] { typeof(string)});
public static Expression<Func<T,
bool >> GetExpression<T>(IList<Filter> filters)
{
if (filters.Count == 0)
return null ;
ParameterExpression param = Expression.Parameter(typeof (T), "t" );
Expression exp = null ;
if (filters.Count == 1)
exp = GetExpression<T>(param, filters[0]);
else if (filters.Count == 2)
exp = GetExpression<T>(param, filters[0], filters[1]);
else
{
while (filters.Count > 0)
{
var f1 = filters[0];
var f2 = filters[1];
if (exp == null )
exp = GetExpression<T>(param, filters[0], filters[1]);
else
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));
filters.Remove(f1);
filters.Remove(f2);
if (filters.Count == 1)
{
exp = Expression .AndAlso(exp, GetExpression<T>(param, filters[0]));
filters.RemoveAt(0);
}
}
}
return Expression.Lambda<Func<T, bool>>(exp, param);
}
private static Expression GetExpression<T>(ParameterExpression param, Filter filter)
{
MemberExpression member = Expression.Property(param, filter.PropertyName);
ConstantExpression constant = Expression.Constant(filter.Value);
switch (filter.Operation)
{
case Op.Equals:
return Expression.Equal(member, constant);
case Op.GreaterThan:
return Expression.GreaterThan(member, constant);
case Op.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, constant);
case Op.LessThan:
return Expression.LessThan(member, constant);
case Op.LessThanOrEqual:
return Expression.LessThanOrEqual(member, constant);
case Op.Contains:
return Expression.Call(member, containsMethod, constant);
case Op.StartsWith:
return Expression.Call(member, startsWithMethod, constant);
case Op.EndsWith:
return Expression.Call(member, endsWithMethod, constant);
}
return null ;
}
private static BinaryExpression GetExpression<T>
(ParameterExpression param, Filter filter1, Filter filter2)
{
Expression bin1 = GetExpression<T>(param, filter1);
Expression bin2 = GetExpression<T>(param, filter2);
return Expression.AndAlso(bin1, bin2);
}
}
// And the filter class has been extended to take a comparison operation as well:
public class Filter
{
public string PropertyName { get ; set ; }
public Op Operation { get ; set ; }
public object Value { get ; set ; }
}
///And the operation is declared as enumeration:
public enum Op
{
Equals,
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
Contains,
StartsWith,
EndsWith
}
//Then the new generic expression builder would be used as follows:
List<Filter> filter = new List<Filter>()
{
new Filter { PropertyName = "City" ,
Operation = Op .Equals, Value = "Mitrovice" },
new Filter { PropertyName = "Name" ,
Operation = Op .StartsWith, Value = "L" },
new Filter { PropertyName = "Salary" ,
Operation = Op .GreaterThan, Value = 9000.0 }
};
var deleg = ExpressionBuilder.GetExpression<Person>(filter).Compile();
var filteredCollection = persons.Where(deleg).ToList();
以上是关于csharp 在Linq中动态构建Where子句的主要内容,如果未能解决你的问题,请参考以下文章
使用 Func<T, string> lambda 动态构造 where 子句 - linq 到实体
LINQ to SQL查询中的C#Dynamic WHERE子句