在刚开始敲代码的时候遇到过这样的事:查询条件多,查询条件不唯一,这个时候需要我们去写非常多的if-else 以及在where写冗长的lamada式

这时候我们可以通过Expression构建动态表达式树来生成所谓的lamada表达式

附上教程;https://ldqk.xyz/1795?kw=%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%A0%91

public class Student
{
[Expression(Wheretype.Equal,Logictype.And)]
public string Banji { get; set; }
[Expression(Wheretype.Equal, Logictype.And)]
public string id { get; set; }
[Expression(Wheretype.Like, Logictype.And)]
public string name { get; set; }
[Expression(Wheretype.Equal, Logictype.And)]
public string url { get; set; }
[Expression(Wheretype.Equal, Logictype.And)]
public string txtName { get; set; }

    public static string Sayname(string name) {
        return "我叫" + name;
    }
}

自定义特性

点击查看代码
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Enum|AttributeTargets.Property)]
public class ExpressionAttribute:Attribute
{
public Logictype logictype{ get; set; }//And 0r
public Wheretype ExpressionName { get { return expre; } }//Equeal、Like
private Wheretype expre { get; set; }
public ExpressionAttribute(Wheretype wheretype,Logictype logictype1) {
expre = wheretype;
logictype = logictype1;
}
public int SwitchType() {
if (expre == Wheretype.Equal && logictype == Logictype.And)
return 1;
if (expre == Wheretype.Equal && logictype == Logictype.Or)
return 2;
if (expre == Wheretype.Like && logictype == Logictype.And)
return 3;
if (expre == Wheretype.Like && logictype == Logictype.Or)
return 4;
return 0;
}
}

public enum Wheretype
{
    Equal,
    Like
}

public enum Logictype
{
    And,
    Or
}

构建的表达式树泛型类

点击查看代码
public class ExpressionBuilder
{
private ParameterExpression para;
private TEntity entity1;
public ExpressionBuilder(TEntity entity){
para = Expression.Parameter(typeof(TEntity),”T”);
this.entity1 = entity;
}

    public BinaryExpression whereAlso =Expression.And(Expression.Constant(true),Expression.Constant(true));
    public Expression Equal(string filed)
    {
        var value= GetVlaue(filed);
        if (value == null)
            return null;
        var prop = Expression.Property(para, filed);
        var eq = Expression.Equal(prop, Expression.Constant(value, value.GetType()));
        return eq;
    }
    public Expression LessThan(string filed)
    {
        var value = GetVlaue(filed);
        if (value is null)
            return null;
        var prop = Expression.Property(para, filed);
        var lessthan = Expression.LessThan(prop, Expression.Constant(value));
        return lessthan;
    }
    public Expression MoreThan(string filed)
    {
        var value = GetVlaue(filed);
        if (value is null)
            return null;
        var prop = Expression.Property(para, filed);
        var morethan = Expression.GreaterThan(prop, Expression.Constant(value));
        return morethan;
    }
    public Expression MoreThanEqual(string filed)
    {
        var value = GetVlaue( filed);
        if (value is null)
            return null;
        var prop = Expression.Property(para, filed);
        var morethan = Expression.GreaterThanOrEqual(prop, Expression.Constant(value));
        return morethan;
    }
    public Expression Like(string filed)
    {
        var value = GetVlaue(filed);
        if (value == null)
            return null;
        var prop = Expression.Property(para,filed);
        var method = typeof(String).GetMethod("Contains", new[] { typeof(string) });
        var call = Expression.Call(prop, method, Expression.Constant(value));
        return call;
    }
    /// <summary>
    /// 获取实体属性值
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="filed"></param>
    /// <returns></returns>
    public object GetVlaue(string filed) {
        var props = typeof(TEntity).GetProperties();
        if (!props.Select(p => p.Name).ToList().Contains(filed))
            return null;
        return props.Where(p => p.Name == filed).FirstOrDefault().GetValue(this.entity1);
    }
    public void And(Expression bianEx) {
        if (bianEx != null)
            this.whereAlso = Expression.AndAlso(whereAlso, bianEx);
    }
    /// <summary>
    /// 创建lamada委托表达式
    /// </summary>
    /// <returns></returns>
    public Expression<Func<TEntity,bool>> CreateLamada()
    {
        if (this.whereAlso != null)
            return Expression.Lambda<Func<TEntity, bool>>(this.whereAlso, para);
        return null;
    }
    public void Or(Expression expression) {
        if (expression != null)
            this.whereAlso = Expression.OrElse(this.whereAlso, expression);
    }
    /// <summary>
    /// 全匹配
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public Expression<Func<TEntity, bool>> Catchall()
    {
        ParameterExpression para = Expression.Parameter(typeof(TEntity), "t");
        if (this.entity1 == null)
            return null;
        BinaryExpression whereExpression = Expression.And(Expression.Constant(true), Expression.Constant(true));
        var props = typeof(TEntity).GetProperties();
        Expression expre = null;
        foreach (var item in props)
        {
            if (item.GetValue(this.entity1) is null)//过滤空值属性
                continue;
            var attr = item.GetCustomAttributes().ToArray()[0] as ExpressionAttribute;
            var prop = Expression.Property(para, item.Name);
            var method = typeof(String).GetMethod("Contains", new[] { typeof(string) });
            switch (attr.SwitchType()) {
                case 1:
                    expre= Expression.Equal(prop, Expression.Constant(item.GetValue(this.entity1)));
                    whereExpression = Expression.And(whereExpression, expre);
                    break;
                case 2:
                    expre = Expression.Equal(prop, Expression.Constant(item.GetValue(this.entity1)));
                    whereExpression = Expression.Or(whereExpression, expre);
                    break;
                case 3:
                    expre = Expression.Call(prop, method, Expression.Constant(GetVlaue(item.Name)));
                    whereExpression = Expression.And(whereExpression, expre);
                    break;
                case 4:
                    expre = Expression.Call(prop, method, Expression.Constant(GetVlaue(item.Name)));
                    whereExpression = Expression.Or(whereExpression, expre);
                    break;
            }
        }
        return Expression.Lambda<Func<TEntity, bool>>(whereExpression, para);
    }

    public Expression In( string filed, string[] objects) {
        var prop = Expression.Property(para,filed);
        var contains = typeof(Enumerable).GetMethods().FirstOrDefault(p => p.GetParameters().Length == 2 && p.Name == "Contains").MakeGenericMethod(typeof(string));
        var call = Expression.Call(null, contains,Expression.Constant(objects), prop);
        return call;
    }
}

数据测试

Student stu = new Student() { id = “15”, name = “s” };//x=>x.id==”15”&&x.name.Contains(“s”)
ExpressionBuilder eb = new ExpressionBuilder(stu);
Console.WriteLine(eb.Catchall());
//eb.And(eb.In(“id”, “17,15”.Split(‘,’)));
//var lamada = eb.CreateLamada();
//Console.WriteLine(lamada);
var list = stus.AsQueryable().Where(eb.Catchall()).ToList();
Console.WriteLine(“筛选之前的数据”);
foreach (var item in stus)
{
Console.WriteLine(item.id + “ “ + item.name);
}
Console.WriteLine(“筛选之后的数据”);
foreach (var item in list)
{
Console.WriteLine(item.id + “ “ + item.name);
}
结果如图

用表达式树构建的In:p=>”15,17”.Split(“,”).Contains(p.id)

Student stu = new Student() { id = “15”, name = “s” };//x=>x.id==”15”&&x.name.Contains(“s”)
ExpressionBuilder eb = new ExpressionBuilder(stu);
Console.WriteLine(eb.Catchall());
eb.And(eb.In(“id”, “17,15”.Split(‘,’)));
var lamada = eb.CreateLamada();
var list = stus.AsQueryable().Where(lamada).ToList();
结果如图

最后:如有不足请多指教