A fast object clone class - using Expression.Compile()
写过一个负责对象克隆功能的类,最近改进了一下,提升了30%的效率:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Testing
{
public static class CloneHelper
{
public static T DeepClone<T>(this T obj)
{
if (obj == null)
return default(T);
var t = obj.GetType();
if (t.IsValueType || t == typeof(string))
return obj;
if (t.IsArray)
return (T)(object)CloneArray((Array)(object)obj, t.GetElementType(), true);
var clone = GetObjectCloner(t, true);
return (T)clone(obj);
}
public static T ShallowClone<T>(this T obj)
{
if (obj == null)
return default(T);
var t = obj.GetType();
if (t.IsValueType || t == typeof(string))
return obj;
if (t.IsArray)
return (T)(object)CloneArray((object[])(object)obj, t.GetElementType(), false);
var clone = GetObjectCloner(t, false);
return (T)clone(obj);
}
private static Array CloneArray(Array array, Type elementType, bool deepclone)
{
var length = array.Length;
var result = Array.CreateInstance(elementType, length);
for (var i = 0; i < length; i++)
{
var element = array.GetValue(i);
var cloned = deepclone
? DeepClone(element)
: element;
result.SetValue(cloned, i);
}
return result;
}
static MethodInfo deepclone_object = StrongTypeReflector.Static.Method(() => CloneHelper.DeepClone<object>(null));
static Dictionary<Type, Func<object, object>> deepcache = new Dictionary<Type, Func<object, object>>();
static Dictionary<Type, Func<object, object>> shallowcache = new Dictionary<Type, Func<object, object>>();
private static Func<object, object> GetObjectCloner(Type type, bool deepclone)
{
Func<object, object> result;
var cache = deepclone
? deepcache
: shallowcache;
if (!cache.TryGetValue(type, out result))
{
var param = Expression.Parameter(typeof(object), "x");
var bindings = new List<MemberAssignment>();
foreach (var field in GetFields(type))
{
var t = field.FieldType;
if (t.IsSubclassOf(typeof(Delegate)))
continue;
var value = Expression.Field(Expression.Convert(param, type), field);
var cloned = (!deepclone) || t.IsValueType || t == typeof(string)
? (Expression)value
: Expression.Convert(Expression.Call(deepclone_object, value), field.FieldType);
bindings.Add(Expression.Bind(field, cloned));
}
var init = Expression.MemberInit(Expression.New(type), bindings.ToArray());
result = Expression.Lambda<Func<object, object>>(init, param).Compile();
cache.Add(type, result);
}
return result;
}
private static IEnumerable<FieldInfo> GetFields(Type type)
{
IEnumerable<FieldInfo> fields = Enumerable.Empty<FieldInfo>();
var t = type;
while (t != null)
{
fields = fields.Concat(t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
t = t.BaseType;
}
return fields;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~