A fast object clone class – using Expression.Compile()

來源:互聯網
上載者:User

寫過一個負責對象複製功能的類,最近改進了一下,提升了30%的效率:

Code
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;
        }
    }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.