Express 表达式目录树的应用
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class People { public int Age { get ; set ; } public string Name { get ; set ; } public int Id; } public class PeopleCopy { public int Age { get ; set ; } public string Name { get ; set ; } public int Id; } |
两个实体类之间的转换做法
1 2 3 4 5 6 | PeopleCopy peopleCopy0 = new PeopleCopy() { Id = people.Id, Name = people.Name, Age = people.Age };性能好,不灵活;不能共用;如果换成其他的类型就不能用了; |
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 | PeopleCopy peopleCopy1 = ReflectionMapper.Trans<People, PeopleCopy>(people); public class ReflectionMapper { /// <summary> /// 反射 /// </summary> /// <typeparam name="TIn"></typeparam> /// <typeparam name="TOut"></typeparam> /// <param name="tIn"></param> /// <returns></returns> public static TOut Trans<TIn, TOut>(TIn tIn) { TOut tOut = Activator.CreateInstance<TOut>(); foreach ( var itemOut in tOut.GetType().GetProperties()) { var propIn = tIn.GetType().GetProperty(itemOut.Name); itemOut.SetValue(tOut, propIn.GetValue(tIn)); } foreach ( var itemOut in tOut.GetType().GetFields()) { var fieldIn = tIn.GetType().GetField(itemOut.Name); itemOut.SetValue(tOut, fieldIn.GetValue(tIn)); } return tOut; } } //反射 灵活,但是性能不好! |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | PeopleCopy peopleCopy2 = SerializeMapper.Trans<People, PeopleCopy>(people); public class SerializeMapper { /// <summary> /// 序列化反序列化方式 /// </summary> /// <typeparam name="TIn"></typeparam> /// <typeparam name="TOut"></typeparam> public static TOut Trans<TIn, TOut>(TIn tIn) { string strJson = JsonConvert.SerializeObject(tIn); return JsonConvert.DeserializeObject<TOut>(strJson); } } //序列化,jason 、xml 灵活,但是性能不好! |
1 2 3 4 5 6 7 | Func<People, PeopleCopy> func = p => new PeopleCopy { Id = p.Id, Name = p.Name, Age = p.Age }; PeopleCopy peopleCopynew = func.Invoke(people);灵活,但是性能不好! |
如果能够把这个委托给缓存起来;根据我们的诉求,缓存一个委托;委托哪儿来?委托其实可以通过表达式目录树Compile一下,就可以得到一个委托;如果拼装一个表达式目录树,再Compile一下,然后缓存起来;就相当于拼装了这一组的转换逻辑;
拼装一下后,缓存下来,如果后面再需要使用,就可以直接使用这个委托了;
动态拼装转换过程;动态拼装了硬编码;
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 | PeopleCopy peopleCopy = ExpressionGenericMapper<People, PeopleCopy>.Trans(people); public class ExpressionGenericMapper<TIn, TOut> //Mapper`2 { private static Func<TIn, TOut> _FUNC = null ; //静态缓存 static ExpressionGenericMapper() { ParameterExpression parameterExpression = Expression.Parameter( typeof (TIn), "p" ); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach ( var item in typeof (TOut).GetProperties()) //反射获取属性 { MemberExpression property = Expression.Property(parameterExpression, typeof (TIn).GetProperty(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } foreach ( var item in typeof (TOut).GetFields()) //反射获取字段 { MemberExpression property = Expression.Field(parameterExpression, typeof (TIn).GetField(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New( typeof (TOut)), memberBindingList.ToArray()); //创建System.Linq.Expressions.MemberInitExpression Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression }); _FUNC = lambda.Compile(); //拼装是一次性的 } public static TOut Trans(TIn t) { return _FUNC(t); } |
也可以用字典缓存,性能不如上面的,会慢几倍
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 | public class ExpressionMapper { /// <summary> /// 字典缓存--hash分布 保存的是委托---委托内部是转换的动作; /// </summary> private static Dictionary< string , object > _Dic = new Dictionary< string , object >(); /// <summary> /// 字典缓存表达式树 /// </summary> /// <typeparam name="TIn"></typeparam> /// <typeparam name="TOut"></typeparam> /// <param name="tIn"></param> /// <returns></returns> public static TOut Trans<TIn, TOut>(TIn tIn) { string key = $ "funckey_{typeof(TIn).FullName}_{typeof(TOut).FullName}" ; if (!_Dic.ContainsKey(key)) { ParameterExpression parameterExpression = Expression.Parameter( typeof (TIn), "p" ); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach ( var item in typeof (TOut).GetProperties()) { MemberExpression property = Expression.Property(parameterExpression, typeof (TIn).GetProperty(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } foreach ( var item in typeof (TOut).GetFields()) { MemberExpression property = Expression.Field(parameterExpression, typeof (TIn).GetField(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New( typeof (TOut)), memberBindingList.ToArray()); Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression }); Func<TIn, TOut> func = lambda.Compile(); //拼装是一次性的 _Dic[key] = func; } return ((Func<TIn, TOut>)_Dic[key]).Invoke(tIn); } } PeopleCopy peopleCopy = ExpressionMapper.Trans<People, PeopleCopy>(people); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现