92 lines
4.2 KiB
C#
92 lines
4.2 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace SamplePre.Common.Helper
|
||
{
|
||
/// <summary>
|
||
/// 实体对象复制工具类(反射实现)
|
||
/// 适配.NET Framework 4.8,支持同实体/不同实体间同名字段值复制(浅拷贝)
|
||
/// </summary>
|
||
public static class ObjectCopyHelper
|
||
{
|
||
/// <summary>
|
||
/// 核心方法:将源对象的同名字段值复制到目标对象
|
||
/// </summary>
|
||
/// <typeparam name="TSource">源对象类型</typeparam>
|
||
/// <typeparam name="TTarget">目标对象类型</typeparam>
|
||
/// <param name="source">源对象(提供值)</param>
|
||
/// <param name="target">目标对象(接收值,需提前实例化)</param>
|
||
/// <param name="ignoreCase">是否忽略属性名大小写(默认true:Name和name视为同一个)</param>
|
||
/// <param name="ignoreNull">是否忽略源对象的null值(默认false:源null会覆盖目标值)</param>
|
||
public static void CopyProperties<TSource, TTarget>(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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重载方法:快速复制(默认忽略大小写、不忽略null)
|
||
/// </summary>
|
||
public static void CopyProperties<TSource, TTarget>(this TSource source, TTarget target)
|
||
where TSource : class
|
||
where TTarget : class
|
||
{
|
||
CopyProperties(source, target, true, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 便捷方法:创建目标对象并完成复制(一步到位,无需提前实例化目标对象)
|
||
/// </summary>
|
||
public static TTarget CopyToNew<TSource, TTarget>(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;
|
||
}
|
||
}
|
||
}
|