


核心代码:
/// <summary>
/// Expression Clone
/// </summary>
public static class DynamicCloneHandler<T> where T : class
{
/// <summary>
/// 初始化
/// </summary>
static DynamicCloneHandler()
{
CloneMethod = CreateCloneMethod();
}
/// <summary>
/// 克隆函数
/// </summary>
private static Action<T, T> CloneMethod;
/// <summary>
/// 创建克隆方法
/// </summary>
/// <param name="type">类型</param>
/// <returns></returns>
private static Action<T, T> CreateCloneMethod()
{
Type type = typeof(T);
ParameterExpression tTarget = Expression.Parameter(type, "TTarget"),
tSource = Expression.Parameter(type, "TSource");
List<BinaryExpression> LsExp = new List<BinaryExpression>(16);
foreach (FieldInfo field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Union(type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)))
{
MemberExpression originalMember = Expression.Field(tSource, field);
MemberExpression newMember = Expression.Field(tTarget, field);
BinaryExpression setValue = Expression.Assign(originalMember, newMember);
LsExp.Add(setValue);
}
BlockExpression body = Expression.Block(typeof(void), LsExp);
return Expression.Lambda<Action<T, T>>(body, tTarget, tSource).Compile();
}
/// <summary>
/// 克隆 instance
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance">clone目标对象</param>
/// <param name="CreateMethod">创建函数</param>
/// <returns></returns>
public static T Clone(T instance, Func<T> CreateMethod)
{
T newIns = CreateMethod();
CloneMethod(newIns, instance);
return newIns;
}
public static T Clone(T instance, T newIns)
{
CloneMethod(newIns, instance);
return newIns;
}
}
因为使用 { get;set; } 这种方式定义“属性”,编译器会自动生成对应的 BackingField 字段,因此无需操作类型的“属性”
测试方法
创建两个类型,TestClass
public class TestClass1 : ICloneable
{
public int ID { get; set; }
public string Name { get; set; }
public string Test;
public int Code { get { return Name.GetHashCode(); } }
public object Clone()
{
return DynamicCloneHandler<TestClass1>.Clone(this, () => new TestClass1());
}
}
public class TestClass2 : ICloneable
{
public int ID { get; set; }
public string Name { get; set; }
public string Test;
public int Code { get { return Name.GetHashCode(); } }
public object Clone()
{
return new TestClass2 { ID = ID, Test = Test, Name = Name };
}
}
分别克隆1千万次

在这里两种克隆方式(直接赋值 和 反射+表达式树)的性能差距——会随着调用次数的增加而减少,间接说明了使用表达式树的方式可以获得接近直接赋值的性能(除了开始的时候反射创建克隆方法)