前言:在DDD系列文章里面,我们在后台仓储里面封装了传递Lamada表达式的通用方法,类似这样:
1
2
3
4
5
|
publicvirtualIQueryable Find(Expressionbool>>express)
{
Funcbool>lamada=express.Compile();
returnUnitOfWork.context.Set().Where(lamada).AsQueryable();
}
|
通过前端传过来的Lamada表达式,直接放到Where条件里面查询。那么问题来了,我们前端如何传入Lamada呢?当然,有人说了,这个不用传啊,前端直接.Find(x=>x.Name==”abc”)这样写就好了啊。确实,如果前端条件只有一个条件,你确实可以这样简单处理,但是实际开发的过程中,我们很多时候是需要传递多个参数,并且.Find(x=>x.Name==”abc”)这种写法也不利于方法的封装。于是,我们神奇的动态Lamada诞生了。
一、再谈Lamada表达式
1、匿名委托
之前在介绍委托的时候我们介绍过一种特殊的匿名委托,它型如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
classProgram
{
privatedelegatevoidSayHello(stringname);
staticvoidMain(string[]args)
{
Say("张三",delegate(stringname)
{
Console.WriteLine("你好,"+name);
});
Say("Zhangsan",delegate(stringname)
{
Console.WriteLine("Hello,"+name);
});
}
staticvoidSay(stringname,SayHello dTest)
{
dTest(name);
}
}
|
也就是说,不用定义一种具体的委托方法去对应SayHello(string name);,而直接delegate(string name){}这样定义一种匿名的委托去执行,这样能减少部分定义具体方法的代码。
2、Lamada表达式进化史
了解了匿名委托的概念,我们来看看我们经常使用的Linq里面的扩展方法Where、Select等。先来看看一般用法:
1
2
|
varlstTest=newListstring>();//.......业务逻辑
varlstRes=lstTest.Where(x=>x.Contains("_"));
|
我们来将Where里面的x => x.Contains(“_”)分解。
初级进化(最原始的匿名委托形式):
1
2
|
Funcstring,bool>oFunc=delegate(stringx){returnx.Contains("_");};
lstRes=lstTest.Where(oFunc);
|
高级进化(型如Lamada,但还有匿名委托的影子):
1
2
|
Funcstring,bool>oFunc=(stringx)=>{returnx.Contains("_");};
lstRes=lstTest.Where(oFunc);
|
究极进化(完完全全的Lamada)
1
2
|
Funcstring,bool>oFunc=x=>x.Contains("_");
lstRes=lstTest.Where(oFunc);
|
有没有很强大,是不是一样一样的。其实这样一看lamada就是匿名委托的缩略形式。x => x.Contains(“_”)表达式左边的表示Func里面的string类型变量,x.Contains(“_”)表示bool类型的返回值。有了这份进化史,程序员再也不用担心面试官问我Lamada怎么回事了。
二、动态Lamada
与其叫动态Lamada,更加严谨一点应该叫动态Expression,因为拼接Lamada表达式用的基本都是Expression的类和方法。博主习惯,暂且就叫它动态Lamada吧。废话不多说,直接吃点栗子吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
publicclassDTO_ORDER
{
publicstringTO_ORDER_ID{get;set;}
publicstringORDER_NO{get;set;}
publicstringORDER_NAME{get;set;}
publicintORDER_STATUS{get;set;}
}
staticvoidMain()
{
//1.定义lamada的参数,型如我们常写的“x=>”
ParameterExpression m_Parameter=Expression.Parameter(typeof(DTO_ORDER),"x");
//2.定义要使用lamada的属性成员(比如我们这里要对DTO_ORDER对象的ORDER_NO属性做筛选)
MemberExpression member=Expression.PropertyOrField(m_Parameter,"ORDER_NO");
//3.定义筛选的操作(是大于、等于、小于、like等)
Expression expRes=Expression.Equal(member,Expression.Constant("aaaa",member.Type));
//4.将表达式转换为Lamada的表达式
Expressionbool>>exprelamada=Expression.Lambdabool>>(expRes,m_Parameter);
varlstRes=newList();
for(vari=0;i10;i++)
{
varoModel=newDTO_ORDER();
oModel.ORDER_NO=i%2==0?"aaaa":"bbbb";
lstRes.Add(oModel);
}
//5.将Expression表达式转换为Func委托,用于Where里面的参数
varlamada=exprelamada.Compile();
lstRes=lstRes.Where(lamada).ToList();
}
|
以上就构造了一个查询List对象里面ORDER_NO 属性等于aaaa的lamada表达式。我们看看运行效果截图:
是不是已经得到了我们想要的表达式!有没有很简单。。。
三、动态Lamada的使用
看到这里有人就郁闷了,为了得到x=>x.ORDER_NO==”aaaa”这种表达式,你绕了这么大一圈,有什么屌用?直接lstRes=lstRes.Where(x=>x.ORDER_NO==”aaaa”);就能够搞定的事,你非要把简单问题复杂化。其实不然,有一定编程经验的朋友肯定知道,一般我们前端传过来的查询参数肯定不会只有一个,当需要查询多个参数时需要我们构造一个统一的Lamada传递到后台;当然你也可以说,我将多个参数全部传递到后台,然后再后台使用IQueryable接口去过滤。当然,这确实可行,但是别忘了我们封装Find(Expression exp…)的意义,不就是为了简化方法么,从这点来说,构造动态Lamada非常必要。
1、通用Lamada表达式类
博主封装了一个简单操作(大于、等于、小于、like等)的动态Lamada类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
publicclassLamadaExtentionwhere Dto:new()
{
privateList m_lstExpression=null;
privateParameterExpression m_Parameter=null;
publicLamadaExtention()
{
m_lstExpression=newList();
m_Parameter=Expression.Parameter(typeof(Dto),"x");
}
//构造表达式,存放到m_lstExpression集合里面
publicvoidGetExpression(stringstrPropertyName,objectstrValue,ExpressionType expressType)
{
Expression expRes=null;
MemberExpression member=Expression.PropertyOrField(m_Parameter,strPropertyName);
if(expressType==ExpressionType.Contains)
{
expRes=Expression.Call(member,typeof(string).GetMethod("Contains"),Expression.Constant(strValue));
}
elseif(expressType==ExpressionType.Equal)
{
expRes=Expression.Equal(member,Expression.Constant(strValue,member.Type));
}
elseif(expressType==ExpressionType.LessThan)
{
expRes=Expression.LessThan(member,Expression.Constant(strValue,member.Type));
}
elseif(expressType==ExpressionType.LessThanOrEqual)
{
expRes=Expression.LessThanOrEqual(member,Expression.Constant(strValue,member.Type));
}
elseif(expressType==ExpressionType.GreaterThan)
{
expRes=Expression.GreaterThan(member,Expression.Constant(strValue,member.Type));
}
elseif(expressType==ExpressionType.GreaterThanOrEqual)
{
expRes=Expression.GreaterThanOrEqual(member,Expression.Constant(strValue,member.Type));
}
//return expRes;
m_lstExpression.Add(expRes);
}
//针对Or条件的表达式
publicvoidGetExpression(stringstrPropertyName,Listobject>lstValue)
{
Expression expRes=null;
MemberExpression member=Expression.PropertyOrField(m_Parameter,strPropertyName);
foreach(varoValue inlstValue)
{
if(expRes==null)
{
expRes=Expression.Equal(member,Expression.Constant(oValue,member.Type));
}
else
{
expRes=Expression.Or(expRes,Expression.Equal(member,Expression.Constant(oValue,member.Type)));
}
}
m_lstExpression.Add(expRes);
}
//得到Lamada表达式的Expression对象
publicExpressionbool>>GetLambda()
{
Expression whereExpr=null;
foreach(varexpr inthis.m_lstExpression)
{
if(whereExpr==null)whereExpr=expr;
elsewhereExpr=Expression.And(whereExpr,expr);
}
if(whereExpr==null)
returnnull;
returnExpression.Lambda>(whereExpr,m_Parameter);
}
}
//用于区分操作的枚举
publicenumExpressionType
{
Contains,//like
Equal,//等于
LessThan,//小于
LessThanOrEqual,//小于等于
GreaterThan,//大于
GreaterThanOrEqual//大于等于
}
|
2、使用场景
博主项目中有某一个页面,查询条件非常多,需要传递到后台很多参数。先来看看页面:
来看后台web api代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
publicobjectGet(intlimit,intoffset,stringstrBodyno,stringstrVin,stringstrOrderno,stringstrEngincode,
stringstrOrderstatus,stringstrTranscode,stringstrVms,stringstrCarcode,
stringstrImportStartdate,stringstrImportEnddate,stringstrSendStartdate,stringstrSendEnddate)
{
//1.定义对象,传入泛型
varoLamadaExtention=newLamadaExtention();
//2.依次构造Lamada表达式
if(!string.IsNullOrEmpty(strBodyno))
{
oLamadaExtention.GetExpression("BODY_NO",strBodyno,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strVin))
{
oLamadaExtention.GetExpression("VIN",strVin,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strOrderno))
{
oLamadaExtention.GetExpression("ORDER_NO",strOrderno,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strEngincode))
{
oLamadaExtention.GetExpression("ENGIN_CODE",strEngincode,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strOrderstatus))
{
if(strOrderstatus.Contains(","))
{
varlstValue=strOrderstatus.Split(",".ToCharArray(),StringSplitOptions.RemoveEmptyEntries).ToList();
varlstObj=newListobject>();
lstValue.ForEach(x=>{
lstObj.Add(Convert.ToInt16(x));
});
oLamadaExtention.GetExpression("ORDER_STATUS",lstObj);
}
else
{
oLamadaExtention.GetExpression("ORDER_STATUS",Convert.ToInt16(strOrderstatus),ExpressionType.Equal);
}
}
if(!string.IsNullOrEmpty(strTranscode))
{
oLamadaExtention.GetExpression("TRANS_CODE",strTranscode,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strVms))
{
oLamadaExtention.GetExpression("VMS_NO",strVms,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strCarcode))
{
oLamadaExtention.GetExpression("TM_MODEL_MATERIAL_ID",strCarcode,ExpressionType.Contains);
}
if(!string.IsNullOrEmpty(strImportStartdate))
{
oLamadaExtention.GetExpression("CREATE_DATE",Convert.ToDateTime(strImportStartdate),ExpressionType.GreaterThanOrEqual);
}
if(!string.IsNullOrEmpty(strImportEnddate))
{
oLamadaExtention.GetExpression("CREATE_DATE",Convert.ToDateTime(strImportEnddate),ExpressionType.LessThanOrEqual);
}
if(!string.IsNullOrEmpty(strSendStartdate))
{
oLamadaExtention.GetExpression("OFFLINE_DATE_ACT",Convert.ToDateTime(strSendStartdate),ExpressionType.GreaterThanOrEqual);
}
if(!string.IsNullOrEmpty(strSendEnddate))
{
oLamadaExtention.GetExpression("OFFLINE_DATE_ACT",Convert.ToDateTime(strSendEnddate),ExpressionType.LessThanOrEqual);
}
//3.得到需要的Lamada表达式Expression
varlamada=oLamadaExtention.GetLambda();
varlstRes=orderManager.Find(lamada).ToList();
//4.得到Bootstrap Table需要的对象
varoRes=newPageRowData();
returnoRes;;
}
|
仓储基类里面的find方法:
1
2
3
4
5
|
publicvirtualIQueryable Find(Expressionbool>>express)
{
Funcbool>lamada=express.Compile();
returnUnitOfWork.context.Set().Where(lamada).AsQueryable();
}
|
四、小结
至此,所谓的动态Lambda就完了。如果你之前用过,请一笑而过;当然如果你没用过,学习点新东西也是好的。请不要嘲笑博主乱下定义,叫动态Lambda挺好的呢。当然你可以叫动态Expression,动态Linq都行,不管叫什么,正确使用才是王道。
相关推荐
在ASP.NET编程中,使用SqlDataReader生成动态Lambda表达式是一种高效的方法,用于将数据库查询结果快速转换为强类型的实体对象。以下是对这个技术的详细解释: 1. **SqlDataReader**: SqlDataReader是ADO.NET中的一...
【SqlDataReader生成动态Lambda表达式】是数据库操作中提高性能的一种技术。在.NET环境中,SqlDataReader是一个高效的数据读取器,用于逐行读取数据库查询结果。然而,将SqlDataReader中的数据映射到自定义实体类...
在.NET框架中,C#是一种强大的编程语言,它支持Lambda表达式,这使得代码更加简洁、易读。Lambda表达式通常用于LINQ(Language Integrated Query)查询,它允许程序员使用类似SQL的语法在内存中的数据集上进行操作。...
煤油工具 煤油库的工具和实用程序,包括: DynamicParser,提供解析动态Lambda表达式,委托并将它们转换为不可知的表达式树的功能 DeepObject,一个多级动态对象 其他实用程序和扩展
1. **静态与动态定位**:LAMBDA算法不仅适用于静态GPS观测,也可用于动态车辆、航空器等实时定位。 2. **其他GNSS系统**:除了GPS,LAMBDA方法也可以应用于GLONASS、Galileo、BeiDou等其他全球导航卫星系统。 3. *...
在某些场景下,我们可能需要动态生成一系列`lambda`函数,根据用户的输入或其他条件进行计算。例如,可以使用字符串数组,将每个字符串转换为`lambda`,然后应用到数据集上。 总结起来,将字符串转换为`lambda`...
Lambda算法的成功应用极大地推动了GPS高精度应用的发展,如静态定位、动态定位、航空导航、惯性导航系统集成以及大地测量等领域。然而,该方法也面临一些挑战,如数据处理的复杂性、实时性能的限制以及对初始化条件...
模糊度求解是全球导航卫星系统(GNSS)定位中的一个重要环节,特别是在高精度静态或动态定位中。LAMBDA(Linear Ambiguity Resolution with the Least-Squares Ambiguity Decorrelation Adjustment)算法是一种广泛...
这个算法在GNSS精密定位领域具有重要意义,特别是在静态、动态以及实时的精密单点定位(Precise Point Positioning, PPP)中,能够高效地解决浮点解到整数解的转换问题,即模糊度解算。 MATLAB是一种强大的数学计算...
而占位符的引入,则使得函数的定义更加灵活,能够适应各种动态的参数需求。 Lambda Chop库的源代码位于`lambda-chop-master`压缩包中,包含了完整的实现和示例。开发者可以通过阅读源码,了解其内部工作原理,并...
- **Web后端服务**:构建动态网站或移动应用后端。 #### 四、高级主题与最佳实践 - **版本控制与别名** - Lambda支持版本控制功能,使得开发者可以轻松地管理和回滚到以前的功能版本。 - 别名则可以指向特定...
route53-dynamic-dns-with-lambda, 使用API网关构建的动态DNS系统,Lambda &路由 53 route53-dynamic-dns-with-lambda使用API网关构建的动态DNS系统,Lambda &路由 53 。这个库中的代码是用来补充完整描述这个项目的...
Lambda表达式本质上是一种匿名函数,即没有名字的函数,它可以用来传递代码或者在运行时动态创建。在C#中,Lambda表达式主要应用于事件处理、LINQ查询以及表达式树的构建。 Lambda表达式的语法结构如下: `(input ...
这一特性在实现动态编程和元编程时特别有用。 #### 小结 Lambda表达式是C# 3.0中的一项重要功能,它不仅简化了代码编写,还提高了代码的可读性和可维护性。通过学习Lambda表达式的基础知识和应用场景,开发人员...
5. **Ansible动态库存**:使用Ansible的动态库存插件,如`aws_ec2`,可以自动发现AWS中的资源,比如EC2实例,这在多环境部署时非常有用。 6. **角色(Roles)和任务(Tasks)**:在playbook中定义角色,将相关的...
表达式树是Lambda表达式的抽象语法树表示,常用于动态构建查询或元编程。 7. **Lambda表达式的限制** 虽然Lambda表达式非常灵活,但它们也有一些限制,比如不能包含控制流语句(如`if`、`for`或`while`)以及无法...
标题中的“基于LAMBDA方法的GPS动态相对定位”指的是使用LAMBDA(Least-squares Ambiguity Decorrelation Adjustment,最小二乘模糊度去相关调整)算法进行GPS动态定位的过程。这种技术是高精度实时动态定位(RTK,...
C++的动态内存管理需要特别注意,以防止内存泄漏或超出分配的内存限制。 4. **异步I/O**:Lambda鼓励非阻塞I/O,以提高并发性和资源利用率。C++的异步编程模型,如std::async、std::future或者第三方库如Boost.Asio...
Java字节码和Lambda表达式之间的关系体现在JVM的LambdaMetafactory机制上,它负责在运行时动态生成对应的函数式类。Lambda表达式在编译后的`.class`文件中,通常以`ClassName$Lambda$1`这样的形式命名,其中`...