Files
SamplePreSystem-CS/SamplePre.Common/Helper/ObjectCopyHelper.cs
2026-04-30 11:34:41 +08:00

92 lines
4.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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">是否忽略属性名大小写默认trueName和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;
}
}
}