C#使用表达式树怎么实现对象复制
发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,本篇内容主要讲解"C#使用表达式树怎么实现对象复制",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C#使用表达式树怎么实现对象复制"吧!需求背景:对象复制性
千家信息网最后更新 2025年01月20日C#使用表达式树怎么实现对象复制
本篇内容主要讲解"C#使用表达式树怎么实现对象复制",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C#使用表达式树怎么实现对象复制"吧!
需求背景:对象复制性能优化;同时,在对象复制时,应跳过引用类型的null值复制,值类型支持值类型向可空类型的复制
using Common;using System;class Program{ static void Main(string[] args) { TestClassA classA = new TestClassA() { PropA = new TestClass() { Name = "cs1" }, PropB = "c1", PropC = 1 }; TestClassA classB = new TestClassA() { PropA = new TestClass() { Name = "cs2" }, PropB = "c2", PropC = 2 }; FastCopy.Copy(classA, classB, false); Console.WriteLine(classB.PropA?.Name + ":" + classB.PropB + ":" + classB.PropC); TestClassA classC = new TestClassA() { PropA = new TestClass() { Name = "cs1" } }; TestClassA classD = new TestClassA() { PropA = new TestClass() { Name = "cs2" }, PropB = "c2", PropC = 2 }; FastCopy.Copy(classC, classD, false); Console.WriteLine(classD.PropA?.Name + ":" + classD.PropB + ":" + classD.PropC); }}public class TestClassA{ public TestClass PropA { get; set; } public string PropB { get; set; } public int? PropC { get; set; }}public class TestClass{ public string Name { get; set; }}
输出:
百万次调用耗时:270-300ms
using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using System.Reflection;using static System.Linq.Expressions.Expression;namespace Common{ public static class FastCopy { static ConcurrentDictionarycopiers = new ConcurrentDictionary (); /// /// 复制两个对象同名属性值 /// ////// /// 源对象 /// 目标对象 /// 源对象属性值为null时,是否将值复制给目标对象 public static void Copy (S source, T target, bool copyNull = true) { string name = string.Format("{0}_{1}_{2}", typeof(S), typeof(T), copyNull); object targetCopier; if (!copiers.TryGetValue(name, out targetCopier)) { Actioncopier = CreateCopier(copyNull); copiers.TryAdd(name, copier); targetCopier = copier; } Actionaction = (Action)targetCopier; action(source, target); } ////// 为指定的两种类型编译生成属性复制委托 /// ////// /// 源对象属性值为null时,是否将值复制给目标对象 /// private static Action CreateCopier(bool copyNull) { ParameterExpression source = Parameter(typeof(S)); ParameterExpression target = Parameter(typeof(T)); var sourceProps = typeof(S).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanRead).ToList(); var targetProps = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanWrite).ToList(); // 查找可进行赋值的属性 var copyProps = targetProps.Where(tProp => sourceProps.Where(sProp => sProp.Name == tProp.Name// 名称一致 且 && ( sProp.PropertyType == tProp.PropertyType// 属性类型一致 或 || sProp.PropertyType.IsAssignableFrom(tProp.PropertyType) // 源属性类型 为 目标属性类型 的 子类;eg:object target = string source; 或 || (tProp.PropertyType.IsValueType && sProp.PropertyType.IsValueType && // 属性为值类型且基础类型一致,但目标属性为可空类型 eg:int? num = int num; ((tProp.PropertyType.GenericTypeArguments.Length > 0 ? tProp.PropertyType.GenericTypeArguments[0] : tProp.PropertyType) == sProp.PropertyType)) )).Count() > 0); ListexpressionList = new List (); foreach (var prop in copyProps) { if (prop.PropertyType.IsValueType)// 属性为值类型 { PropertyInfo sProp = typeof(S).GetProperty(prop.Name); PropertyInfo tProp = typeof(T).GetProperty(prop.Name); if (sProp.PropertyType == tProp.PropertyType)// 属性类型一致 eg:int num = int num; 或 int? num = int? num; { var assign = Assign(Property(target, prop.Name), Property(source, prop.Name)); expressionList.Add(assign); } else if (sProp.PropertyType.GenericTypeArguments.Length <= 0 && tProp.PropertyType.GenericTypeArguments.Length > 0)// 属性类型不一致且目标属性类型为可空类型 eg:int? num = int num; { var convert = Convert(Expression.Property(source, prop.Name), tProp.PropertyType); var cvAssign = Assign(Expression.Property(target, prop.Name), convert); expressionList.Add(cvAssign); } } else// 属性为引用类型 { var assign = Assign(Property(target, prop.Name), Property(source, prop.Name));// 编译生成属性赋值语句 target.{PropertyName} = source.{PropertyName}; var sourcePropIsNull = Equal(Constant(null, prop.PropertyType), Property(source, prop.Name));// 判断源属性值是否为Null;编译生成 source.{PropertyName} == null var setNull = IsTrue(Constant(copyNull));// 判断是否复制Null值 编译生成 copyNull == True var setNullTest = IfThen(setNull, assign); var condition = IfThenElse(sourcePropIsNull, setNullTest, assign); /** * 编译生成 * if(source.{PropertyName} == null) * { * if(setNull) * { * target.{PropertyName} = source.{PropertyName}; * } * } * else * { * target.{PropertyName} = source.{PropertyName}; * } */ expressionList.Add(condition); } } var block = Block(expressionList.ToArray()); Expression > lambda = Lambda >(block, source, target); return lambda.Compile(); } }}
如果完整复制,去掉逻辑判断,同时可通过泛型类,不在使用字典,性能还可以提升。
using System;using System.Linq;using System.Linq.Expressions;using System.Reflection;namespace Common{ public static class FastCopy{ static Actionaction = CreateCopier(); ////// 复制两个对象同名属性值 /// ////// /// 源对象 /// 目标对象 /// 源对象属性值为null时,是否将值复制给目标对象 public static void Copy(S source, T target, bool copyNull = true) { action(source, target); } /// /// 为指定的两种类型编译生成属性复制委托 /// ////// /// 源对象属性值为null时,是否将值复制给目标对象 /// private static Action CreateCopier() { ParameterExpression source = Expression.Parameter(typeof(S)); ParameterExpression target = Expression.Parameter(typeof(T)); var sourceProps = typeof(S).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanRead).ToList(); var targetProps = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanWrite).ToList(); // 查找可进行赋值的属性 var copyProps = targetProps.Where(tProp => sourceProps.Where(sProp => sProp.Name == tProp.Name// 名称一致 且 && ( sProp.PropertyType == tProp.PropertyType// 属性类型一致 )).Count() > 0); var block = Expression.Block(from p in copyProps select Expression.Assign(Expression.Property(target, p.Name), Expression.Property(source, p.Name))); Expression> lambda = Expression.Lambda >(block, source, target); return lambda.Compile(); } }}
百万次耗时:100ms左右
到此,相信大家对"C#使用表达式树怎么实现对象复制"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
属性
对象
类型
目标
一致
生成
编译
表达式
C#
两个
内容
同时
名称
性能
委托
学习
实用
更深
兴趣
基础
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
电商分析软件开发
vpn服务器未响应
数据库的三级分类
gt7无法登陆服务器
腾讯云服务器开启smtp
简要说明空间数据库的核心作用
ubuntu安装svn服务器
什么是客户机与web服务器通信
南充市互联网科技公司
服务器启动安全模式
卫生院网络安全等级保护工作
用电脑单机攻击器能攻破服务器吗
数据库的事物操作
堡垒机和数据库的区别
qt 调用数据库查询
黑客删除数据库
软件开发从事的工作好找吗
数据库date返回当前系统日期
数据库盗取
反恐网络安全国旗下讲话
重点时段网络安全防控
网络安全使用
服务器usb口可以挂移动硬盘吗
我国网络安全管理规定
开发管理和使用数据库人员主要有
信息网络安全还是网络信息安全
公司网络安全顾问
新锐网络安全绘画
对数据库信息进行增删
网络安全编程密码置换