using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace SamplePre.Common.Helper { /// /// 实体对象复制工具类(反射实现) /// 适配.NET Framework 4.8,支持同实体/不同实体间同名字段值复制(浅拷贝) /// public static class ObjectCopyHelper { /// /// 核心方法:将源对象的同名字段值复制到目标对象 /// /// 源对象类型 /// 目标对象类型 /// 源对象(提供值) /// 目标对象(接收值,需提前实例化) /// 是否忽略属性名大小写(默认true:Name和name视为同一个) /// 是否忽略源对象的null值(默认false:源null会覆盖目标值) public static void CopyProperties(this TSource source, TTarget target, bool ignoreCase = true, bool ignoreNull = false) where TSource : class // 源对象不能为空引用类型 where TTarget : class // 目标对象不能为空引用类型 { // 空值校验 if (source == null) throw new ArgumentNullException(nameof(source), "源对象不能为null"); if (target == null) throw new ArgumentNullException(nameof(target), "目标对象不能为null"); // 获取源对象和目标对象的属性信息(仅获取公共可读写属性) PropertyInfo[] sourceProps = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance); PropertyInfo[] targetProps = typeof(TTarget).GetProperties(BindingFlags.Public | BindingFlags.Instance); // 遍历源对象的所有属性,匹配目标对象的同名字段 foreach (PropertyInfo sourceProp in sourceProps) { // 跳过源对象中不可读的属性(无getter) if (!sourceProp.CanRead) continue; // 获取源对象当前属性的值 object sourceValue = sourceProp.GetValue(source, null); // 忽略源对象的null值(若开启该配置) if (ignoreNull && sourceValue == null) continue; // 在目标对象中查找同名字段(支持忽略大小写) PropertyInfo targetProp = Array.Find(targetProps, p => string.Equals(p.Name, sourceProp.Name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)); // 目标对象无该属性/目标属性不可写/类型不匹配 → 跳过 if (targetProp == null || !targetProp.CanWrite || !sourceProp.PropertyType.IsAssignableFrom(targetProp.PropertyType)) { continue; } // 给目标对象的属性赋值 targetProp.SetValue(target, sourceValue, null); } } /// /// 重载方法:快速复制(默认忽略大小写、不忽略null) /// public static void CopyProperties(this TSource source, TTarget target) where TSource : class where TTarget : class { CopyProperties(source, target, true, false); } /// /// 便捷方法:创建目标对象并完成复制(一步到位,无需提前实例化目标对象) /// public static TTarget CopyToNew(this TSource source, bool ignoreCase = true, bool ignoreNull = false) where TSource : class where TTarget : class, new() // 目标对象必须有无参构造函数 { if (source == null) throw new ArgumentNullException(nameof(source)); // 实例化目标对象并赋值 TTarget target = new TTarget(); source.CopyProperties(target, ignoreCase, ignoreNull); return target; } } }