微软.net表达式编译居然有bug?
微软.net表达式编译问题困扰本人很久了,
为此我整理了以下case给大家分享
1. 可行性调研
- 用表达式把一个对象转化为另一个对象
 - 当一个类含有多个同类型属性时,把相同类型转化提取为公共方法
 - LambdaExpression可以用来定义复用的公共方法
 - 一切看起来都很完美,但是居然翻车了!!!
 
2. 示例说明
2.1 Customer多个属性包含Address
对应CustomerDTO多个属性包含AddressDTO
public class Customer
{
public string Name { get; set; }
public Address Address { get; set; }
public Address[] Addresses { get; set; }
public List<Address> AddressList { get; set; }
}
public class CustomerDTO
{
public string Name { get; set; }
public AddressDTO Address { get; set; }
public AddressDTO[] Addresses { get; set; }
public List<AddressDTO> AddressList { get; set; }
}
2.2 定义公共方法把Address转化为AddressDTO
/// <summary>
/// 定义转化 Address -> AddressDTO
/// </summary>
/// <returns></returns>
public static Expression<Func<Address, AddressDTO>> CreateAddressDTO()
{
var sourceType = typeof(Address);
var destType = typeof(AddressDTO);
// Address source;
var source = Expression.Parameter(sourceType, "source");
// AddressDTO dest;
var dest = Expression.Parameter(destType, "dest");
var body = Expression.Block(
[dest],
// dest = new AddressDTO();
Expression.Assign(dest, Expression.New(destType)),
// dest.City = source.City;
Expression.Assign(Expression.Property(dest, "City"), Expression.Property(source, "City")),
// return dest;
dest
);
return Expression.Lambda<Func<Address, AddressDTO>>(body, source);
}
2.3 调用公共方法
/// <summary>
/// 定义转化委托 Customer -> CustomerDTO
/// </summary>
/// <returns></returns>
public static Expression<Func<Customer, CustomerDTO>> CreateCustomerDTO()
{
var customerType = typeof(Customer);
var dtoType = typeof(CustomerDTO);
// Customer customer;
var customer = Expression.Parameter(customerType, "customer");
// CustomerDTO dto;
var dto = Expression.Parameter(dtoType, "dto");
// 可以复用的功能方法
var addressDTOConvertFunc = CreateAddressDTO();
var body = Expression.Block(
[dto],
// dto = new AddressDTO();
Expression.Assign(dto, Expression.New(dtoType)),
// dto.Name = customer.Name;
Expression.Assign(Expression.Property(dto, "Name"), Expression.Property(customer, "Name")),
// dto.Address = addressDTOConvertFunc.Invoke(customer.Address);
ConvertAddress(addressDTOConvertFunc, customer, dto),
// dto.Addresses
ConvertAddresses(addressDTOConvertFunc, customer, dto),
// dto.AddressList
ConvertAddressList(addressDTOConvertFunc, customer, dto),
// return dto
dto
);
return Expression.Lambda<Func<Customer, CustomerDTO>>(body, customer);
}
以上看上去是不是很完美!!!
但是马上就要翻车了...
2.4 测试一下
var expression = CreateCustomerDTO();
var func = expression.Compile();
Customer _customer = new()
{
Name = "jxj",
Address = new() { City = "gz" },
AddressList = [new() { City = "bj" }],
Addresses = [new() { City = "sh" }]
};
var dto = func(_customer);
// {"Name":"jxj","Address":{"City":"gz"},"Addresses":[{"City":"sh"}],"AddressList":[]}
2.4.1 请大家围观翻车现场
- Address和Addresses转化成功了,但是AddressList转化失败了
 - 如果说LambdaExpression不能复用,为什么Address和Addresses共用LambdaExpression能成功
 - 而且如果删掉Addresses属性AddressList就能转化成功
 
2.5 换成FastExpressionCompiler再测试一下
var expression = CreateCustomerDTO();
var func = FastExpressionCompiler.ExpressionCompiler.CompileFast<Func<Customer, CustomerDTO>>(expression);
Customer _customer = new()
{
Name = "jxj",
Address = new() { City = "gz" },
AddressList = [new() { City = "bj" }],
Addresses = [new() { City = "sh" }]
};
var dto = func(_customer);
// {"Name":"jxj","Address":{"City":"gz"},"Addresses":[{"City":"sh"}],"AddressList":[{"City":"bj"}]}
换成FastExpressionCompiler全部成功,这是不是实锤是微软的bug
3. 附两个note对比示例
- expression_fast.dib是微软转化失败示例
 - expression_fast.dib是FastExpressionCompiler转化成功示例
 - 大家可以下载本地执行
 
微软.net表达式编译居然有bug?的更多相关文章
- 带你玩转Visual Studio——带你理解微软的预编译头技术
		
原文地址:http://blog.csdn.net/luoweifu/article/details/49010627 不陌生的stdafx.h 还记得带你玩转Visual Studio——带你新建一 ...
 - [转]微软word的多级列表的bug的解决办法和吐槽
		
原文地址:https://blog.csdn.net/haoyujie/article/details/80601455 1. 问题引出 这向天,在编写一系列文档. 其中一篇要今天交,前天写好后,一 ...
 - 【Not BUG】微软Winform窗体中设计上的Bug,会导致程序编译失败?不,这不是BUG!
		
这不是BUG!!! 原文地址: https://www.cnblogs.com/thanks/p/14302011.html 现在让我们回忆一下原文 原文的操作步骤: 1. 新建一个Window Fo ...
 - 给IDEA道个歉,这不是它的BUG,而是反编译插件的BUG。
		
你好呀,我是歪歪. 上周我不是发了<我怀疑这是IDEA的BUG,但是我翻遍全网没找到证据!>这篇文章吗. 主要描述了在 IDEA 里面反编译后的 class 文件中有这样的代码片段: 很明 ...
 - 用了 10 多年的 Tomcat 居然有bug !
		
Java技术栈 www.javastack.cn 优秀的Java技术公众号 为了解决分布式链路追踪的问题,我们引入了实现OpenTracing的Jaeger来实现.然后我们为SpringBoot框架写 ...
 - [工作札记]03: 微软Winform窗体中ListView、DataGridView等控件的Bug,会导致程序编译失败,影响范围:到最新的.net4.7.2都有
		
工作中,我们发现了微软.net WinForm的一个Bug,会导致窗体设计器自动生成的代码失效,这个Bug从.net4.5到最新的.net4.7.2都存在,一直没有解决.最初是我在教学工作中发现的,后 ...
 - 那些年黑了你的微软BUG
		
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 前言 炎炎夏日,朗朗乾坤,30℃ 的北京,你还在 Coding 吗? 整个 7 月都在忙项目,还加了 ...
 - 微软BI 之SSIS 系列 - MVP 们也不解的 Scrip Task 脚本任务中的一个 Bug
		
开篇介绍 前些天自己在整理 SSIS 2012 资料的时候发现了一个功能设计上的疑似Bug,在 Script Task 中是可以给只读列表中的变量赋值.我记得以前在 2008 的版本中为了弄明白这个配 ...
 - C语言中史上最愚蠢的Bug
		
C语言中史上最愚蠢的Bug 本文来自“The most stupid C bug ever”,很有意思,分享给大家.我相信这样的bug,就算你是高手你也会犯的.你来看看作者犯的这个Bug吧.. 首 ...
 - C#中的Lambda表达式和表达式树
		
在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...
 
随机推荐
- 表的连接方式介绍(NESTED LOOP, SORT MERGE JOIN, HASH JOIN )
			
循环嵌套链接(NESTED LOOP) 嵌套循环链接的内部处理的流程如下. Oracle 优化器根据基于规则RBO或基于成本CBO的原则,选择两个表中的一个作为驱动表,并指定其为外部表. Oracle ...
 - 禁止后退Js 兼容各个浏览器
			
<script src="${ctxPath}/media/lib/jquery.history.js"></script> <script> ...
 - poi处理excel的合并单元格写的工具类,支持xlsx和xls
			
1.判断当前单元格是不是合并单元格 1 ... 2 private boolean isMergedRegion(Sheet sheet, int row, int column) { 3 //获取合 ...
 - taro小程序日期选择器
			
taro-swiper-week taro-swiper-week 是一个基于 taro 的日期选择器控件. 可以用在h5.微信小程序等众多平台! 简体中文 | English 使用 先安装 npm ...
 - es6的迭代器和生成器
			
迭代器es6新增的特性,之前没有,其语法借鉴了Python. Java. C++. Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代List 和 Set 等集合. 实现了 ...
 - left join 和 where 区别
			
RT https://leetcode.cn/problems/replace-employee-id-with-the-unique-identifier/solution/ select b.un ...
 - JDK 7  和  JDK 8 的区别
			
简介 容易记的 jdk8支持接口可以添加默认方法, default; jdk8支持lambda表达式 jdk7中hashmap解决冲突采用链表, 一旦hash碰撞过多, 可能会使得一个链表上存在多个节 ...
 - virtual studio  插入 函数注释头  snippet方式
			
简介 以前通过一个插件就可以管理所有的函数,也可以通过snippet插入 参考链接 如何使用snippet https://blog.csdn.net/weixin_30278237/article/ ...
 - java ColorChooser
			
简介 java 核心编程 创建了三个chooser.一个是模态,一个是非模态,一个是非模态实时. 放入别的frame 进行了展示 image code /* * @Author: your name ...
 - Docker部署RestCloud ETL社区
			
镜像说明 nriet/restcloud:latest version:1.3.0 os:slim-buster tomcat:基于官方镜像 tomcat:8.5.78-jdk8-openjdk-sl ...