使用 PropertyInfo 和值为 Linq Where 构建动态表达式

Build Dynamic Expression For Linq Where using PropertyInfo and a value

如标​​题所述,我想使用 propertyInfo 和一个值构建一个动态表达式。

目前我有这样的东西

public static IQueryable<T> WhereValueEquals<T>(this IQueryable<T> q, FieldFor fieldFor, string fieldValue) 
        where T : ModuleData
    {
        switch (fieldFor)
        {
            case FieldFor.Name:
                return q.Where(e => e.Name == fieldValue);
            case FieldFor.Reference:
                return q.Where(e => e.Reference == fieldValue);
            case FieldFor.Text0:
                return q.Where(e => e.Reference == fieldValue);

            default:
                return q;
        }
    }

现在 case 语句只会越来越长,但这在开发的早期阶段很好。

现在,使用 FieldFor 枚举,我可以使用我已经编写的扩展来获取 propertyInfo。那么我如何使用传入的字符串值和 propertyInfo

来自 WhereValueEquals 的 IQueryable return

到目前为止我有

public static IQueryable<T> WhereValueEquals<T>(this IQueryable<T> q, FieldFor fieldFor, string fieldValue) 
    where T : ModuleData
{
    PropertyInfo propertyInfo = typeof(T).GetFieldProperties().GetPropertyByFieldFor(fieldFor);            

    //return q.Where(expression);
}

有时我不得不做类似的事情,Whosebug 上有大量代码向您展示如何构建表达式生成器。这是我的 POC,希望对你有帮助

void Main()
{
    var ops  = new List<Ops>
    { 
        new Ops
        {
            //OperandType = typeof(string), 
            OpType=OpType.Equals, 
            OperandName = "Name", 
            ValueToCompare = "MM"
        },
        new Ops
        {
            //OperandType = typeof(int), 
            OpType=OpType.Equals, 
            OperandName = "ID", 
            ValueToCompare = 1
        },
    };
    var testClasses = new List<TestClass>
    {
        new TestClass { ID =1, Name = "MM", Date = new DateTime(2014,12,1)},
        new TestClass { ID =2, Name = "BB", Date = new DateTime(2014,12,2)}
    };

    var funct = ExpressionBuilder.BuildExpressions<TestClass>(ops);
    foreach(var item in testClasses.Where(funct))
    {
        Console.WriteLine("ID " +item.ID);
        Console.WriteLine("Name " +item.Name);
        Console.WriteLine("Date" + item.Date);
    }
}

// 在这里定义其他方法和类

public enum OpType
{
    Equals
}

public class Ops
{
    //public Type OperandType {get; set;}

    public OpType OpType {get; set;}

    public string OperandName {get;set;}

    public object ValueToCompare {get;set;}
}

public class TestClass
{   
    public int ID {get;set;}
    public string Name {get; set;}
    public DateTime Date {get;set;}
}

public class ExpressionBuilder
{
    public static Func<T,bool> BuildExpressions<T>( List<Ops> opList)
    {
        Expression currentExpression= null;
        var parameter = Expression.Parameter(typeof(T), "prop");
        for(int i =0; i< opList.Count; i++)
        {
            var op =  opList[i];
            Expression innerExpression = null;
            switch(op.OpType)
            {
                case OpType.Equals :
                {
                    var innerParameter = Expression.Property(parameter,op.OperandName);
                    var ConstExpression = Expression.Constant(op.ValueToCompare);
                    innerExpression = Expression.Equal(innerParameter, ConstExpression);
                    break;
                }
            }

            if (i >0)
            {
                currentExpression = Expression.And(currentExpression, innerExpression);
            }
            else
            {
                currentExpression = innerExpression;
            }
        }
        var lambdaExpression = Expression.Lambda<Func<T,bool>>(currentExpression, new []{parameter});
        Console.WriteLine(lambdaExpression);
        return lambdaExpression.Compile() ;
    }
}