C#中Lambda表达式的精妙之处

我在文章中写的内容大约花了10个小时,而这是10个小时的连续调试,这减少了对代码的工作版本和非工作版本的逐步比较,甚至没有从代码的工作窗口和非工作版本的调试窗口中比较每一行。


对于不熟悉表达式树的程序员, 有关msdn的一篇很好的入门文章详细介绍了构建树的一些步骤,而我在本文中省略了这些步骤。


在这种情况下,该测试将变为绿色(启用EF加载项,如果无法将查询完全转换为SQL ,则该加载项将崩溃)。



  • 首先,必须定义PupilName字段的映射(如果未定义), 查询提供程序无法识别要投影到SQL ORDER BY PupilName属性。
  • 其次,提供者必须解析此映射,例如,它将不起作用, EF将开始宣誓(默认情况下,它不宣誓,它将引发内存中的实体-LINQ to Object ,但是可以启用 ):




事实是, 查询提供程序无法理解我们要对实体进行分类的属性。 但是,如果正确编写了映射,则提供程序将应对,发送SQL查询,接收响应并反序列化结果。


有时需要自己编写Expressions ,即类似的东西:



我将向您展示如何编写此表达式 ,这并不难,上面的链接提供了几个类似的示例:



我们将逐步收集lambda,首先收集一个参数,一个属性,然后将所有内容粘合在一起。
在这种情况下,这将不起作用,并且测试将变为绿色(提供程序将无法解析表达式)?


不知道吗 不用担心,我也不知道,最后我花了大约10个小时来理解。
这是一个提示,它将起作用:



PupilDto从PupilDtoBase继承


事实是,如果PupilName属性本身属于基类,则需要从基类中获取 PropertyInfo,因此C#构建lambda表达式 ,然后EF依靠语言标准对其进行解析。


证明

如果在OrderBy中编写常规lambda, 调试器将显示什么:



在我们的情况下,如下所示:



AutoMapper和IncludeBase


如果您尝试不重复代码,那么您可能会遇到DTOIncludeBase的继承:



还有一个更复杂的情况:



这个测试将是绿色的:



事情是一样的,再次从接口中提取PropertyInfo



证明

Age属性的ReflectedType是一个接口, IPupilDto ,C#构建一个lambda,其中Age属性是PupilDto类的属性,而不是接口,但是自动映射器如何构建lambda:



如何解决这个问题? 如果具有接口的IncludeBase Automapper不适合我们(如果您在内存中使用映射-不会影响您),那么您将不得不放弃此API,我通过在扩展方法中突出显示映射来解决此问题,如下所示:



然后,自动映射器本身将通过名称找到合适的type属性,构建“正确的” lambda
感谢您的关注!

Source: https://habr.com/ru/post/zh-CN453720/


All Articles