Lambda表达式c#经验谈:巧⽤Expression表达式解决类似于
sql中select。。。
我们在项⽬经常会碰到⼀些特殊需求 例如下拉框是复选的,查询条件是根据下拉框中复选项进⾏拼接
看到此图后⼤家肯定会说,这很简单嘛
将所有的选项 拼成“'1-3','5-9'”  然后放到 in 的字句后⾯,⼀查就出来了。
这样做的确在逻辑上没有问题,可是⼤家有没有想过这个问题,过度的和业务耦合虽然能够解决
现在的需求但是却牺牲了代码优雅和可维护性
其实本⽂的⽬的是想利⽤Expression表达式在linq查询中实现⼀个优雅的解决⽅案,
同时也会给⼤家⼀个⽤Expression去拼接sql的思路
先上代码
public static Expression<Func<T, bool>> GetConditionExpression<T>(string[] options, string fieldName)
sql中select是什么意思{
ParameterExpression left = Expression.Parameter(typeof(T), "c");//c=>
Expression expression = Expression.Constant(false);
foreach (var optionName in options)
{
Expression right = Expression.Call
(
Expression.Property(left, typeof(T).GetProperty(fieldName)),  //c.DataSourceName
typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),// 反射使⽤.Contains()⽅法
s Expression.Constant(optionName)          // .Contains(optionName)
);
expression = Expression.Or(right, expression);//ain("") || ain("")
}
Expression<Func<T, bool>> finalExpression
= Expression.Lambda<Func<T, bool>>(expression, new ParameterExpression[] { left });
return finalExpression;
}
复制代码
我想⽤逆推的⽅式说明下这段代码,其实我们查询的⽬的要实现这样的效果 ,
someList.where(c=>ains("someName")||c.Name.Contains("someName")||...)
1. ⾸先我们要确定返回什么样的表达式,根据经验.where后⾯是需要⼀个Expression<Func<T, bool>> 这样的⼀个表达式,所以⽅法的返
回类型已经能确定下来了
2. 接下来的任务是拼接类似于c=>c.Name.Contains("") 这样的表达式,按照⾃左向右的原则,左侧表达式参数c很好理解 就是T,那么这个
表达式的参数也就搞定了,
可以⽤Expression.Parameter⽅法来实现,该⽅法⽬的是将类型反射并且映射给表达式中的匿名变量 “c” (也可以理解成将参数常量封装成表达式)
3. 接着是表达式右侧的拼接
再次仔细看下这段代码
Expression right = Expression.Call
(
Expression.Property(left, typeof(T).GetProperty(fieldName)),  //c.DataSourceName    ⾸先是反射获取c的⼀个属
typeof(string).GetMethod("Contains",new Type[] { typeof(string) }),// 声明⼀个string.Contains的⽅
法  c.DataSourceName.Contains()                反射使⽤.Contains()⽅法
Expression.Constant(optionName)          //  c.DataSourceName.Contains(optionName)              封装常量
);
为什么要使⽤Expression.Call ?
(因为ains 属于ains()这个⽅法所以我们必须将该⽅法封装成表达式,Expression.Call的功能就是将⽅法封装成表达式)
这时候⼤家会问contains什么呢? 当然常量option虽然是string类型,但是仍需封装成表达式,Expression.Constant(optionName) 起到了封装常量的作⽤
于是c=>c.属性.Contains(常量) 这个表达式搞定,可是还是有问题:怎么加上“||” ,聪明的你已经有了答案,Expression.Or()
4 最后⼀步当然⾮常关键,就像产品需要通过流⽔线进⾏包装组合,表达式也不例外:
Expression.Lambda<Func<T, bool>>(expression, new ParameterExpression[] { left });
对于整个表达式来说,左侧是参数表达式(ParameterExpression),Expression.Lambda就是=>符号,就右侧表达式和参数表达式通过lambda符号进⾏组合,搞定
这样的话,你只需传⼊⼀个字符串数组就能在Linq中实现类似于sql中select in 的效果了,
很多朋友肯定会问,既然能够⽤⾃定义表达式搞定,那么可不可以将表达式的思路⽤于拼接sql?
答案是肯定的。但是如果业务逻辑⾮常复杂,⽽且难以把握,还是建议⽤ado 配合存过实现
感谢⼥友⼀直陪到深夜,让我坚持把这篇博⽂写完,⽂中如有错误,也请⼤家海涵并且能够及时告诉我,谢谢!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。