c#表達式樹實現淺拷貝對象

表達式樹淺拷貝對象、反射淺拷貝對象對比手寫的Copy方法100萬次耗時對比(CPU是 i7 - 4710MQ)

static void Main(string[] args)
{
    var value = new TestClass
    {
        Age = 18,
        Name = "張三",
        Sex = Gender.Man
    };
    Console.WriteLine("-------手寫代碼------");
    for (int j = 0; j < 5; j++)
    {
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 1000000; i++)
        {
            var copyValue = Copy(value);//手寫的Copy
        }
        sw.Stop();
        Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
    }
    Console.WriteLine("-------表達式樹------");
    for (int j = 0; j < 5; j++)
    {
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 1000000; i++)
        {
            var copyValue = ShallowCopy<TestClass>.Copy(value);//表達式樹實現的Copy【程序啓動的第一次Copy需要編譯會慢一點】
        }
        sw.Stop();
        Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
    }
    Console.WriteLine("-------反射生成------");
    for (int j = 0; j < 5; j++)
    {
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 1000000; i++)
        {
            var copyValue = ShallowCopyReflect<TestClass>.Copy(value);//反射實現Copy
        }
        sw.Stop();
        Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
    }
}
public static TestClass Copy(TestClass value)
{
    return new TestClass
    {
        Age = value.Age,
        Name = value.Name,
        Sex = value.Sex
    };
}

public class TestClass
{
    public int Age { get; set; }
    public string Name { get; set; }
    public Gender Sex { get; set; }
}

public enum Gender
{
    Man = 0,
    Woman = 1
}

耗時:↓

-------手寫代碼------
42.7358ms
36.8807ms
35.0374ms
34.8473ms
35.1947ms
-------表達式樹------
132.8095ms
132.7188ms
124.1226ms
124.3291ms
124.0487ms
-------反射生成------
2501.8246ms
2357.8119ms
2353.0715ms
2351.2028ms
2341.6874ms

表達式樹Copy類

/// <summary>
/// 淺拷貝類
/// </summary>
/// <typeparam name="T">拷貝的類型</typeparam>
public static class ShallowCopy<T> where T : new()
{
    /// <summary>
    /// 淺拷貝委託對象樹
    /// </summary>
    private static readonly Func<T, T> CopyFunc;

    static ShallowCopy()
    {
        var value = Expression.Parameter(typeof(T));
        var copyValue = Expression.New(typeof(T));
        var bindProValues = typeof(T).GetProperties().Where(w => w.CanWrite && w.CanRead).Select(pro => Expression.Bind(pro, Expression.Property(value, pro))).ToArray();
        var initProValue = Expression.MemberInit(copyValue, bindProValues);
        var lambda = Expression.Lambda<Func<T, T>>(initProValue, new[] { value });
        CopyFunc = lambda.Compile();
    }

    /// <summary>
    /// 拷貝方法
    /// </summary>
    /// <param name="value">需要被拷貝的值</param>
    /// <returns>拷貝的值</returns>
    public static T Copy(T value)
    {
        if (value == null) return default(T);
        return CopyFunc(value);
    }
}

反射實現的Copy類

/// <summary>
/// 淺拷貝類反射實現
/// </summary>
/// <typeparam name="T">拷貝的類型</typeparam>
public static class ShallowCopyReflect<T> where T : new()
{
    private readonly static PropertyInfo[] Properties;
    private readonly static ConstructorInfo Constructor;
    static ShallowCopyReflect()
    {
        Properties = typeof(T).GetProperties().Where(w => w.CanWrite && w.CanRead).ToArray();
        Constructor = typeof(T).GetConstructor(new Type[0]);
    }
    /// <summary>
    /// 拷貝方法
    /// </summary>
    /// <param name="value">需要被拷貝的值</param>
    /// <returns>拷貝的值</returns>
    public static T Copy(T value)
    {
        if (value == null) return default(T);
        var copyValue = Constructor.Invoke(null);
        foreach (var property in Properties)
        {
            property.SetValue(copyValue, property.GetValue(value));
        }
        return (T)copyValue;
    }
}
發佈了53 篇原創文章 · 獲贊 56 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章