动态创建表达式有啥好处呢?
灵活性强与良好的扩展性是它的最大优点,我们以代码来直观的表示,先简单了解下它的基本语法:
//委托,封装一个f方法(三个参数,其中最后一个参数是返回值类型)
Func<string, string, int> f = (s1, s2) => (s1 + s2).Length;
Console.WriteLine(f("你好", "hi"));//4
//表达式目录树using System.Linq.Expressions;
Expression<Func<string, int, bool>> exp = (n, m) => ((n + m).Length > 5);
Console.WriteLine(exp);//(n, m) => ((n + Convert(m)).Length > 5)
Console.WriteLine(exp.Compile());//System.Func`3[System.String,System.Int32,System.Boolean]
Console.WriteLine(exp.Compile()("hi", 123));//False
再进一步来看个简单的Lambda表达式是怎么创建出来的
//(a, b) => ((a / b) + 5)
ParameterExpression paraLeft = Expression.Parameter(typeof(int), "a");
ParameterExpression paraRight = Expression.Parameter(typeof(int), "b");
BinaryExpression binaryLeft = Expression.Divide(paraLeft, paraRight);
ConstantExpression conRight = Expression.Constant(5, typeof(int));
BinaryExpression binaryBody = Expression.Add(binaryLeft, conRight);
LambdaExpression lambda = Expression.Lambda<Func<int, int, int>>(binaryBody, paraLeft, paraRight);
Func<int, int, int> func = lambda.Compile() as Func<int, int, int>;
Console.WriteLine(func(6, 3));//7
最后我们来构建一个条件查询语句,做多条件查询的时候,基本的SQL都是写死的,比较繁琐,现在我们来动态构建
//---------------动态创建表达式目录树---------------//
//名字模糊查询tony
//年龄大于等于20
//年龄小于30
string uname = "tony";
List<Expression> expList = new List<Expression>(2);
ParameterExpression parExp = Expression.Parameter(typeof(UserInfo), "infos");//创建需要查找的参数
//查姓名infos.UserName.Contains("tony")
MemberExpression unameExp = Expression.Property(parExp, "UserName");
MethodInfo containsMethod = typeof(string).GetMethod("Contains");//using System.Reflection;指定实现Contains方法
ConstantExpression unamevalueExp = Expression.Constant(uname, typeof(string));
MethodCallExpression containsExp = Expression.Call(unameExp, containsMethod, unamevalueExp);
expList.Add(containsExp);
//查年龄infos.Age>=20
MemberExpression age1 = Expression.Property(parExp, "Age");
ConstantExpression agevalue1 = Expression.Constant(20, typeof(int));
BinaryExpression gteExp = Expression.GreaterThanOrEqual(age1, agevalue1);
expList.Add(gteExp);
//查年龄infos.Age<30
//if (1 > 2)
//{
MemberExpression age2 = Expression.Property(parExp, "Age");
ConstantExpression agevalue2 = Expression.Constant(30, typeof(int));
BinaryExpression ltExp = Expression.LessThan(age2, agevalue2);
expList.Add(ltExp);
//}
//把上面的表达式连接起来
Expression whereExp = null;
foreach (var item in expList)
{
if (whereExp == null)
{
whereExp = item;
}
else
{
whereExp = Expression.And(whereExp, item);
}
}
//生成Lambda表达式
//Expression<Func<UserInfo, bool>> lambda = Expression.Lambda<Func<UserInfo, bool>>(whereExp, parExp);
LambdaExpression lambda = Expression.Lambda<Func<UserInfo, bool>>(whereExp, parExp);
Console.WriteLine(lambda);
/*
* 生成结果:
* infos => ((infos.UserName.Contains("tony") And (infos.Age>=20)) And (infos.Age<30))
*/