Files
tnb.server/common/Tnb.Common/Utils/DeepCopyHelper.cs

77 lines
3.0 KiB
C#
Raw 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.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Tnb.Common.Utils
{
public class DeepCopyHelper<T> where T : class, new() // 需要无参构造函数,构造表达式树的时候需要利用无参构造函数创建对象
{
/// <summary>
/// 映射表达式,泛型缓存每个类型存一份
/// </summary>
private static readonly Func<T, T> s_CopyFunc = null;
/// <summary>
/// 静态构造函数,每个泛型类型会且只会执行一次
/// </summary>
static DeepCopyHelper()
{
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "m"); // 参数m :m =>
List<MemberBinding> memberBindingList = new List<MemberBinding>();
foreach (var item in typeof(T).GetProperties(bindingFlags))
{
if (!item.CanWrite) // 只读属性不拷贝
{
continue;
}
MemberExpression property = Expression.Property(parameterExpression, item); // m.Name
MemberBinding memberBinding = Expression.Bind(item, property); // Name = m.Name
memberBindingList.Add(memberBinding);
}
foreach (var item in typeof(T).GetFields(bindingFlags))
{
MemberExpression property = Expression.Field(parameterExpression, item);
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindingList.ToArray());// new T() {Name = m.Name}
Expression<Func<T, T>> lambda = Expression.Lambda<Func<T, T>>(memberInitExpression, new ParameterExpression[]
{
parameterExpression
}); // m => new T() {Name = m.Name}
s_CopyFunc = lambda.Compile();
}
/// <summary>
/// 对象拷贝拷贝private/public实例成员、属性、静态成员
/// </summary>
/// <param name="data">源</param>
/// <returns></returns>
public static T DeepCopy(T data)
{
return s_CopyFunc(data);
}
/// <summary>
/// 集合拷贝拷贝private/public实例成员、属性、静态成员
/// </summary>
/// <param name="data">源</param>
/// <returns></returns>
public static List<T> DeepCopyList(List<T> data)
{
if (data == null || data.Count < 1)
{
return Enumerable.Empty<T>().ToList();
}
return data.Select(a => DeepCopy(a)).ToList();
}
}
}