Linq Func linq 鍙戦煶
创始人
2024-06-06 17:50:51
0

本文我们开始Linq利用表达式树,并讨论比较有趣的内容,即如何实现Linq Func

在Linq中,任何接收λ表达式(委托类型)的方法都可以转换为接收相同委托类型的Expression的方法,并且不需要更改客户机代码。例如:

  1. privatestaticvoid DoSomething(Predicate predicate)  

可以替换为:

  1. privatestaticvoid DoSomething(  
  2. Expression> predicate) 

在上述两种情况下,调用代码可以是相同的λ表达式:

  1. DoSomething(x => x.Value > 25); 

这里发生的情况是,编译器不会将指针传入到第二个方法签名的匿名委托中,而是生成以表达式树的形式构建AST(抽象语法树)的IL代码。如果您打开Reflector(我的类型反射类的名字也由此而来,它是任何高级开发人员都应该经常使用的最伟大的工具)并取消对DoSomething的方法调用,就可以看到:

  1. ParameterExpression expression1 =  
  2. Expression.Parameter(typeof(Mock), "x");  
  3. Program.DoSomething(  
  4. Expression.Lambda>(  
  5. Expression.GT(Expression.Field(  
  6. expression1, fieldof(Mock.Value)),  
  7. Expression.Constant(0x19, typeof(int))),  
  8. newParameterExpression[]{expression1 })  
  9. );  

这里您可以看到编译器如何使用Expression类上的静态方法构建整个表达式(我对API的详细看法另外单独讨论)。当然,在方法实现中,您可以检查相同的树并执行任何想执行的操作。***的Linq CTP包含一个非常酷的可视化工具,在运行时到达您的方法主体时可以用来查看表达式树中的情况。到现在为止,您应该明白了我正在实现一个强类型反射:我接收一个表达式树,并在其中搜索方法调用节点(或者,对于属性和字段来说是成员访问)。下面是Method<>方法的实现:

  1. publicstaticMethodInfo Method(  
  2. Expression method)  
  3. {  
  4. return GetMethodInfo(method);  
  5. }  
  6.    
  7. privatestaticMethodInfo GetMethodInfo(Expression method)  
  8. {  
  9. LambdaExpression lambda = method asLambdaExpression;  
  10. if (lambda == null)  
  11. thrownewArgumentNullException("method");  
  12.  
  13. MethodCallExpression methodExpr = null;  
  14.    
  15. // 我们的Operation返回一个对象,故首先可以声名一  
  16. // 个类型转换(如果方法无返回对象)或直接方法调用。  
  17. if (lambda.Body.NodeType == ExpressionType.Cast)  
  18. {  
  19. // 类型转换是一个一元操作,而操作数是一个方法调用表达式。  
  20. methodExpr = ((UnaryExpression)lambda.Body).  
  21. Operand asMethodCallExpression;  
  22. }  
  23. elseif (lambda.Body.NodeType == ExpressionType.MethodCall ||  
  24. lambda.Body.NodeType == ExpressionType.MethodCallVirtual)  
  25. {  
  26. methodExpr = lambda.Body asMethodCallExpression;  
  27. }  
  28. if (methodExpr == null)  
  29. thrownewArgumentException("method");  
  30. return methodExpr.Method;  
  31. }  

我创建的就是Operation委托类型。不能使用Linq Func(以及T、Arg0……),因为它们返回的是布尔值。我需要更灵活的对象,简单来说就是返回对象的对象,以及接收一些固定参数类型(例如Func)的委托“重载”。因此我得到如下内容:

  1. publicdelegateobjectOperation();  
  2. publicdelegateobjectOperation(T declaringType);  
  3. publicdelegateobjectOperation(T declaringType, A0 arg0);  
  4. ...  

注意,API的用户从来都不会知道这些委托类型的对象的存在,就像查询操作符的用户从不知道Func的存在一样。我希望将来这些委托能够消失,而代之以更好的东西(可能是publicdelegateobject Operation < params T> ;))。此外,注意我是如何将新的参数类型的参数添加到T“后面”的,T是重载的通用转换,与Linq Func中的功能正好相反。

【编辑推荐】

  1. LINQ to SQL Table浅谈
  2. Linq语句问题的解决方法
  3. Ling to sql更新实体概述
  4. Linq实体继承简单描述
  5. Linq Library概述

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...