Exemplo n.º 1
0
        public static T CloneObject <T>(T obj)
        {
            // this is faster than typeof(T).IsValueType
            if (obj is ValueType)
            {
                if (typeof(T) == obj.GetType())
                {
                    return(obj);
                }

                // we're here so, we clone value type obj as object type T
                // so, we need to copy it, bcs we have a reference, not real object.
                return((T)ShallowObjectCloner.CloneObject(obj));
            }

            if (ReferenceEquals(obj, null))
            {
                return((T)(object)null);
            }

            if (DeepClonerSafeTypes.CanReturnSameObject(obj.GetType()))
            {
                return(obj);
            }

            return((T)ShallowObjectCloner.CloneObject(obj));
        }
Exemplo n.º 2
0
        private static object GenerateProcessArrayMethod(Type type, bool isDeep)
        {
            Type elementType = type.GetElementType();
            int  arrayRank   = type.GetArrayRank();
            ParameterExpression parameterExpression  = Expression.Parameter(typeof(object));
            ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object));
            ParameterExpression parameterExpression3 = Expression.Parameter(typeof(DeepCloneState));
            Type delegateType = typeof(Func <, , ,>).MakeGenericType(typeof(object), typeof(object), typeof(DeepCloneState), typeof(object));

            if (arrayRank == 1 && type == elementType.MakeArrayType())
            {
                if (!isDeep)
                {
                    MethodCallExpression body = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod("ShallowClone1DimArraySafeInternal").MakeGenericMethod(elementType), Expression.Convert(parameterExpression, type), Expression.Convert(parameterExpression2, type));
                    return(Expression.Lambda(delegateType, body, parameterExpression, parameterExpression2, parameterExpression3).Compile());
                }
                string methodName = "Clone1DimArrayClassInternal";
                if (DeepClonerSafeTypes.CanNotCopyType(elementType, null))
                {
                    methodName = "Clone1DimArraySafeInternal";
                }
                else if (elementType.IsValueType())
                {
                    methodName = "Clone1DimArrayStructInternal";
                }
                MethodCallExpression body2 = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType), Expression.Convert(parameterExpression, type), Expression.Convert(parameterExpression2, type), parameterExpression3);
                return(Expression.Lambda(delegateType, body2, parameterExpression, parameterExpression2, parameterExpression3).Compile());
            }
            MethodCallExpression body3 = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod((arrayRank == 2 && type == elementType.MakeArrayType()) ? "Clone2DimArrayInternal" : "CloneAbstractArrayInternal"), Expression.Convert(parameterExpression, type), Expression.Convert(parameterExpression2, type), parameterExpression3, Expression.Constant(isDeep));

            return(Expression.Lambda(delegateType, body3, parameterExpression, parameterExpression2, parameterExpression3).Compile());
        }
Exemplo n.º 3
0
        private static object CloneClassRoot(object obj)
        {
            if (obj == null)
            {
                return(null);
            }

            // we can receive an poco objects which is faster to copy in shallow way if possible
            var type = obj.GetType();

            // 200ms
            if (DeepClonerSafeTypes.IsClassSafe(type))
            {
                return(ShallowObjectCloner.CloneObject(obj));
            }
            // 350ms
            var cloner = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(type, t => GenerateCloner(t, true));

            if (cloner == null)
            {
                return(obj);
            }

            // 200ms
            return(cloner(obj, new DeepCloneState()));
        }
Exemplo n.º 4
0
        private static object GenerateProcessArrayMethod(Type type)
        {
            Type       elementType = type.GetElementType();
            int        arrayRank   = type.GetArrayRank();
            MethodInfo method;

            if (arrayRank != 1 || type != elementType.MakeArrayType())
            {
                method = ((arrayRank != 2 || !(type == elementType.MakeArrayType())) ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneAbstractArrayInternal") : typeof(DeepClonerGenerator).GetPrivateStaticMethod("Clone2DimArrayInternal").MakeGenericMethod(elementType));
            }
            else
            {
                string methodName = "Clone1DimArrayClassInternal";
                if (DeepClonerSafeTypes.CanNotCopyType(elementType, null))
                {
                    methodName = "Clone1DimArraySafeInternal";
                }
                else if (elementType.IsValueType())
                {
                    methodName = "Clone1DimArrayStructInternal";
                }
                method = typeof(DeepClonerGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType);
            }
            ParameterExpression  parameterExpression  = Expression.Parameter(typeof(object));
            ParameterExpression  parameterExpression2 = Expression.Parameter(typeof(DeepCloneState));
            MethodCallExpression body = Expression.Call(method, Expression.Convert(parameterExpression, type), parameterExpression2);

            return(Expression.Lambda(typeof(Func <, ,>).MakeGenericType(typeof(object), typeof(DeepCloneState), typeof(object)), body, parameterExpression, parameterExpression2).Compile());
        }
Exemplo n.º 5
0
 internal static object GenerateClonerInternal(Type realType, bool asObject)
 {
     if (DeepClonerSafeTypes.CanNotCopyType(realType, null))
     {
         return(null);
     }
     return(GenerateProcessMethod(realType, asObject && realType.IsValueType()));
 }
Exemplo n.º 6
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep)
        {
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            int num  = Math.Min(objFrom.GetLength(0), objTo.GetLength(0));
            int num2 = Math.Min(objFrom.GetLength(1), objTo.GetLength(1));

            state.AddKnownRef(objFrom, objTo);
            if ((!isDeep || DeepClonerSafeTypes.CanNotCopyType(typeof(T), null)) && objFrom.GetLength(0) == objTo.GetLength(0) && objFrom.GetLength(1) == objTo.GetLength(1))
            {
                Array.Copy(objFrom, objTo, objFrom.Length);
                return(objTo);
            }
            if (!isDeep)
            {
                for (int i = 0; i < num; i++)
                {
                    for (int j = 0; j < num2; j++)
                    {
                        int num3 = i;
                        int num4 = j;
                        T   val  = objFrom[i, j];
                        objTo[num3, num4] = val;
                    }
                }
                return(objTo);
            }
            if (typeof(T).IsValueType())
            {
                Func <T, DeepCloneState, T> clonerForValueType = DeepClonerGenerator.GetClonerForValueType <T>();
                for (int k = 0; k < num; k++)
                {
                    for (int l = 0; l < num2; l++)
                    {
                        int num5 = k;
                        int num6 = l;
                        T   val2 = clonerForValueType(objFrom[k, l], state);
                        objTo[num5, num6] = val2;
                    }
                }
            }
            else
            {
                for (int m = 0; m < num; m++)
                {
                    for (int n = 0; n < num2; n++)
                    {
                        int num7 = m;
                        int num8 = n;
                        T   obj  = (T)DeepClonerGenerator.CloneClassInternal(objFrom[m, n], state);
                        objTo[num7, num8] = obj;
                    }
                }
            }
            return(objTo);
        }
Exemplo n.º 7
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep)
        {
            // not null from called method, but will check it anyway
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            var l1 = Math.Min(objFrom.GetLength(0), objTo.GetLength(0));
            var l2 = Math.Min(objFrom.GetLength(1), objTo.GetLength(1));

            state.AddKnownRef(objFrom, objTo);
            if ((!isDeep || DeepClonerSafeTypes.CanReturnSameObject(typeof(T))) &&
                objFrom.GetLength(0) == objTo.GetLength(0) &&
                objFrom.GetLength(1) == objTo.GetLength(1))
            {
                Array.Copy(objFrom, objTo, objFrom.Length);
                return(objTo);
            }

            if (!isDeep)
            {
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        objTo[i, k] = objFrom[i, k];
                    }
                }
                return(objTo);
            }

            if (typeof(T).IsValueType())
            {
                var cloner = DeepClonerGenerator.GetClonerForValueType <T>();
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        objTo[i, k] = cloner(objFrom[i, k], state);
                    }
                }
            }
            else
            {
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        objTo[i, k] = (T)DeepClonerGenerator.CloneClassInternal(objFrom[i, k], state);
                    }
                }
            }

            return(objTo);
        }
Exemplo n.º 8
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }
            int length  = obj.GetLength(0);
            int length2 = obj.GetLength(1);

            T[,] array = new T[length, length2];
            state.AddKnownRef(obj, array);
            if (DeepClonerSafeTypes.CanNotCopyType(typeof(T), null))
            {
                Array.Copy(obj, array, obj.Length);
                return(array);
            }
            if (typeof(T).IsValueType())
            {
                Func <T, DeepCloneState, T> clonerForValueType = GetClonerForValueType <T>();
                for (int i = 0; i < length; i++)
                {
                    for (int j = 0; j < length2; j++)
                    {
                        T[,] array2 = array;
                        int num  = i;
                        int num2 = j;
                        T   val  = clonerForValueType(obj[i, j], state);
                        array2[num, num2] = val;
                    }
                }
            }
            else
            {
                for (int k = 0; k < length; k++)
                {
                    for (int l = 0; l < length2; l++)
                    {
                        T[,] array3 = array;
                        int num3 = k;
                        int num4 = l;
                        T   obj2 = (T)CloneClassInternal(obj[k, l], state);
                        array3[num3, num4] = obj2;
                    }
                }
            }
            return(array);
        }
Exemplo n.º 9
0
        private static object GenerateProcessArrayMethod(Type type, bool isDeep)
        {
            var elementType = type.GetElementType();
            var rank        = type.GetArrayRank();

            ParameterExpression from = Expression.Parameter(typeof(object));
            ParameterExpression to   = Expression.Parameter(typeof(object));
            var state = Expression.Parameter(typeof(DeepCloneState));

            var funcType = typeof(Func <, , ,>).MakeGenericType(typeof(object), typeof(object), typeof(DeepCloneState), typeof(object));

            if (rank == 1 && type == elementType.MakeArrayType())
            {
                if (!isDeep)
                {
                    var callS = Expression.Call(
                        typeof(ClonerToExprGenerator).GetPrivateStaticMethod("ShallowClone1DimArraySafeInternal")
                        .MakeGenericMethod(elementType), Expression.Convert(from, type), Expression.Convert(to, type));
                    return(Expression.Lambda(funcType, callS, from, to, state).Compile());
                }
                else
                {
                    var methodName = "Clone1DimArrayClassInternal";
                    if (DeepClonerSafeTypes.CanReturnSameObject(elementType))
                    {
                        methodName = "Clone1DimArraySafeInternal";
                    }
                    else if (elementType.IsValueType())
                    {
                        methodName = "Clone1DimArrayStructInternal";
                    }
                    var methodInfo = typeof(ClonerToExprGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType);
                    var callS      = Expression.Call(methodInfo, Expression.Convert(from, type), Expression.Convert(to, type), state);
                    return(Expression.Lambda(funcType, callS, from, to, state).Compile());
                }
            }
            else
            {
                // multidim or not zero-based arrays
                var methodInfo = typeof(ClonerToExprGenerator).GetPrivateStaticMethod(
                    rank == 2 && type == elementType.MakeArrayType()
                                                ? "Clone2DimArrayInternal"
                                                : "CloneAbstractArrayInternal");
                var callS = Expression.Call(methodInfo, Expression.Convert(from, type), Expression.Convert(to, type), state, Expression.Constant(isDeep));
                return(Expression.Lambda(funcType, callS, from, to, state).Compile());
            }
        }
Exemplo n.º 10
0
        public static T CloneObject <T>(T obj)
        {
            if (obj is ValueType)
            {
                var type = obj.GetType();
                if (typeof(T) == type)
                {
                    if (DeepClonerSafeTypes.CanReturnSameObject(type))
                    {
                        return(obj);
                    }

                    return(CloneStructInternal(obj, new DeepCloneState()));
                }
            }

            return((T)CloneClassRoot(obj));
        }
Exemplo n.º 11
0
        private static object GenerateProcessArrayMethod(Type type)
        {
            var elementType = type.GetElementType();
            var rank        = type.GetArrayRank();

            MethodInfo methodInfo;

            // multidim or not zero-based arrays
            if (rank != 1 || type != elementType.MakeArrayType())
            {
                if (rank == 2 && type == elementType.MakeArrayType())
                {
                    // small optimization for 2 dim arrays
                    methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod("Clone2DimArrayInternal").MakeGenericMethod(elementType);
                }
                else
                {
                    methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneAbstractArrayInternal");
                }
            }
            else
            {
                var methodName = "Clone1DimArrayClassInternal";
                if (DeepClonerSafeTypes.IsTypeSafe(elementType, null))
                {
                    methodName = "Clone1DimArraySafeInternal";
                }
                else if (elementType.IsValueType())
                {
                    methodName = "Clone1DimArrayStructInternal";
                }
                methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType);
            }

            ParameterExpression from = Expression.Parameter(typeof(object));
            var state = Expression.Parameter(typeof(DeepCloneState));
            var call  = Expression.Call(methodInfo, Expression.Convert(from, type), state);

            var funcType = typeof(Func <, ,>).MakeGenericType(typeof(object), typeof(DeepCloneState), typeof(object));

            return(Expression.Lambda(funcType, call, from, state).Compile());
        }
Exemplo n.º 12
0
        // relatively frequent case. specially handled
        internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (obj == null)
            {
                return(null);
            }
            var l1       = obj.GetLength(0);
            var l2       = obj.GetLength(1);
            var outArray = new T[l1, l2];

            state.AddKnownRef(obj, outArray);
            if (DeepClonerSafeTypes.IsTypeSafe(typeof(T), null))
            {
                Array.Copy(obj, outArray, obj.Length);
                return(outArray);
            }

            if (typeof(T).IsValueType())
            {
                var cloner = GetClonerForValueType <T>();
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        outArray[i, k] = cloner(obj[i, k], state);
                    }
                }
            }
            else
            {
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        outArray[i, k] = (T)CloneClassInternal(obj[i, k], state);
                    }
                }
            }

            return(outArray);
        }
Exemplo n.º 13
0
        private static object CloneClassRoot(object obj)
        {
            if (obj == null)
            {
                return(null);
            }
            Type type = obj.GetType();

            if (DeepClonerSafeTypes.CanNotDeepCopyClass(type))
            {
                return(ShallowObjectCloner.CloneObject(obj));
            }
            Func <object, DeepCloneState, object> func = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(type, (Type t) => GenerateCloner(t, true));

            if (func == null)
            {
                return(obj);
            }
            return(func(obj, new DeepCloneState()));
        }
Exemplo n.º 14
0
        private static object GenerateCloner(Type t, bool asObject)
        {
            if (DeepClonerSafeTypes.CanReturnSameObject(t) && (asObject && !t.IsValueType()))
            {
                return(null);
            }

#if !NETCORE
            if (ShallowObjectCloner.IsSafeVariant())
            {
                return(DeepClonerExprGenerator.GenerateClonerInternal(t, asObject));
            }
            else
            {
                return(DeepClonerMsilGenerator.GenerateClonerInternal(t, asObject));
            }
#else
            return(DeepClonerExprGenerator.GenerateClonerInternal(t, asObject));
#endif
        }
Exemplo n.º 15
0
        private static object GenerateProcessMethod(Type type, bool unboxStruct)
        {
            if (type.IsArray)
            {
                return(GenerateProcessArrayMethod(type));
            }

            var methodType = unboxStruct || type.IsClass() ? typeof(object) : type;

            var expressionList = new List <Expression>();

            ParameterExpression from = Expression.Parameter(methodType);
            var fromLocal            = from;
            var toLocal = Expression.Variable(type);
            var state   = Expression.Parameter(typeof(DeepCloneState));

            if (!type.IsValueType())
            {
                var methodInfo = typeof(object).GetPrivateMethod("MemberwiseClone");

                // to = (T)from.MemberwiseClone()
                expressionList.Add(Expression.Assign(toLocal, Expression.Convert(Expression.Call(from, methodInfo), type)));

                fromLocal = Expression.Variable(type);
                // fromLocal = (T)from
                expressionList.Add(Expression.Assign(fromLocal, Expression.Convert(from, type)));

                // added from -> to binding to ensure reference loop handling
                // structs cannot loop here
                // state.AddKnownRef(from, to)
                expressionList.Add(Expression.Call(state, typeof(DeepCloneState).GetMethod("AddKnownRef"), from, toLocal));
            }
            else
            {
                if (unboxStruct)
                {
                    // toLocal = (T)from;
                    expressionList.Add(Expression.Assign(toLocal, Expression.Unbox(from, type)));
                    fromLocal = Expression.Variable(type);
                    // fromLocal = toLocal; // structs, it is ok to copy
                    expressionList.Add(Expression.Assign(fromLocal, toLocal));
                }
                else
                {
                    // toLocal = from
                    expressionList.Add(Expression.Assign(toLocal, from));
                }
            }

            List <FieldInfo> fi = new List <FieldInfo>();
            var tp = type;

            do
            {
#if !NETCORE
                // don't do anything with this dark magic!
                if (tp == typeof(ContextBoundObject))
                {
                    break;
                }
#else
                if (tp.Name == "ContextBoundObject")
                {
                    break;
                }
#endif

                fi.AddRange(tp.GetDeclaredFields());
                tp = tp.BaseType();
            }while (tp != null);

            foreach (var fieldInfo in fi)
            {
                if (!DeepClonerSafeTypes.IsTypeSafe(fieldInfo.FieldType, null))
                {
                    var methodInfo = fieldInfo.FieldType.IsValueType()
                                                                                ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal")
                                     .MakeGenericMethod(fieldInfo.FieldType)
                                                                                : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal");

                    var get = Expression.Field(fromLocal, fieldInfo);

                    // toLocal.Field = Clone...Internal(fromLocal.Field)
                    var call = (Expression)Expression.Call(methodInfo, get, state);
                    if (!fieldInfo.FieldType.IsValueType())
                    {
                        call = Expression.Convert(call, fieldInfo.FieldType);
                    }

                    // should handle specially
                    // todo: think about optimization, but it rare case
                    if (fieldInfo.IsInitOnly)
                    {
                        // var setMethod = fieldInfo.GetType().GetMethod("SetValue", new[] { typeof(object), typeof(object) });
                        // expressionList.Add(Expression.Call(Expression.Constant(fieldInfo), setMethod, toLocal, call));
                        var setMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField");
                        expressionList.Add(Expression.Call(setMethod, Expression.Constant(fieldInfo), Expression.Convert(toLocal, typeof(object)), Expression.Convert(call, typeof(object))));
                    }
                    else
                    {
                        expressionList.Add(Expression.Assign(Expression.Field(toLocal, fieldInfo), call));
                    }
                }
            }

            expressionList.Add(Expression.Convert(toLocal, methodType));

            var funcType = typeof(Func <, ,>).MakeGenericType(methodType, typeof(DeepCloneState), methodType);

            var blockParams = new List <ParameterExpression>();
            if (from != fromLocal)
            {
                blockParams.Add(fromLocal);
            }
            blockParams.Add(toLocal);

            return(Expression.Lambda(funcType, Expression.Block(blockParams, expressionList), from, state).Compile());
        }
Exemplo n.º 16
0
        private static object GenerateProcessMethod(Type type, bool unboxStruct)
        {
            if (type.IsArray)
            {
                return(GenerateProcessArrayMethod(type));
            }

            if (type.FullName != null && type.FullName.StartsWith("System.Tuple`"))
            {
                // if not safe type it is no guarantee that some type will contain reference to
                // this tuple. In usual way, we're creating new object, setting reference for it
                // and filling data. For tuple, we will fill data before creating object
                // (in constructor arguments)
                var genericArguments = type.GenericArguments();
                // current tuples contain only 8 arguments, but may be in future...
                // we'll write code that works with it
                if (genericArguments.Length < 10 && genericArguments.All(DeepClonerSafeTypes.CanReturnSameObject))
                {
                    return(GenerateProcessTupleMethod(type));
                }
            }

            var methodType = unboxStruct || type.IsClass() ? typeof(object) : type;

            var expressionList = new List <Expression>();

            ParameterExpression from = Expression.Parameter(methodType);
            var fromLocal            = from;
            var toLocal = Expression.Variable(type);
            var state   = Expression.Parameter(typeof(DeepCloneState));

            if (!type.IsValueType())
            {
                var methodInfo = typeof(object).GetPrivateMethod("MemberwiseClone");

                // to = (T)from.MemberwiseClone()
                expressionList.Add(Expression.Assign(toLocal, Expression.Convert(Expression.Call(from, methodInfo), type)));

                fromLocal = Expression.Variable(type);
                // fromLocal = (T)from
                expressionList.Add(Expression.Assign(fromLocal, Expression.Convert(from, type)));

                // added from -> to binding to ensure reference loop handling
                // structs cannot loop here
                // state.AddKnownRef(from, to)
                expressionList.Add(Expression.Call(state, typeof(DeepCloneState).GetMethod("AddKnownRef"), from, toLocal));
            }
            else
            {
                if (unboxStruct)
                {
                    // toLocal = (T)from;
                    expressionList.Add(Expression.Assign(toLocal, Expression.Unbox(from, type)));
                    fromLocal = Expression.Variable(type);
                    // fromLocal = toLocal; // structs, it is ok to copy
                    expressionList.Add(Expression.Assign(fromLocal, toLocal));
                }
                else
                {
                    // toLocal = from
                    expressionList.Add(Expression.Assign(toLocal, from));
                }
            }

            List <FieldInfo> fi = new List <FieldInfo>();
            var tp = type;

            do
            {
#if !NETCORE
                // don't do anything with this dark magic!
                if (tp == typeof(ContextBoundObject))
                {
                    break;
                }
#else
                if (tp.Name == "ContextBoundObject")
                {
                    break;
                }
#endif

                fi.AddRange(tp.GetDeclaredFields());
                tp = tp.BaseType();
            }while (tp != null);

            foreach (var fieldInfo in fi)
            {
                if (!DeepClonerSafeTypes.CanReturnSameObject(fieldInfo.FieldType))
                {
                    var methodInfo = fieldInfo.FieldType.IsValueType()
                                                                                ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal")
                                     .MakeGenericMethod(fieldInfo.FieldType)
                                                                                : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal");

                    var get = Expression.Field(fromLocal, fieldInfo);

                    // toLocal.Field = Clone...Internal(fromLocal.Field)
                    var call = (Expression)Expression.Call(methodInfo, get, state);
                    if (!fieldInfo.FieldType.IsValueType())
                    {
                        call = Expression.Convert(call, fieldInfo.FieldType);
                    }

                    // should handle specially
                    // todo: think about optimization, but it rare case
                    if (fieldInfo.IsInitOnly)
                    {
                        // var setMethod = fieldInfo.GetType().GetMethod("SetValue", new[] { typeof(object), typeof(object) });
                        // expressionList.Add(Expression.Call(Expression.Constant(fieldInfo), setMethod, toLocal, call));
                        var setMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField");
                        expressionList.Add(Expression.Call(setMethod, Expression.Constant(fieldInfo), Expression.Convert(toLocal, typeof(object)), Expression.Convert(call, typeof(object))));
                    }
                    else
                    {
                        expressionList.Add(Expression.Assign(Expression.Field(toLocal, fieldInfo), call));
                    }
                }
            }

            expressionList.Add(Expression.Convert(toLocal, methodType));

            var funcType = typeof(Func <, ,>).MakeGenericType(methodType, typeof(DeepCloneState), methodType);

            var blockParams = new List <ParameterExpression>();
            if (from != fromLocal)
            {
                blockParams.Add(fromLocal);
            }
            blockParams.Add(toLocal);

            return(Expression.Lambda(funcType, Expression.Block(blockParams, expressionList), from, state).Compile());
        }
Exemplo n.º 17
0
        private static object GenerateProcessMethod(Type type, bool isDeepClone)
        {
            if (type.IsArray)
            {
                return(GenerateProcessArrayMethod(type, isDeepClone));
            }
            Type typeFromHandle      = typeof(object);
            List <Expression>   list = new List <Expression>();
            ParameterExpression parameterExpression  = Expression.Parameter(typeFromHandle);
            ParameterExpression parameterExpression2 = parameterExpression;
            ParameterExpression parameterExpression3 = Expression.Parameter(typeFromHandle);
            ParameterExpression parameterExpression4 = parameterExpression3;
            ParameterExpression parameterExpression5 = Expression.Parameter(typeof(DeepCloneState));

            parameterExpression2 = Expression.Variable(type);
            parameterExpression4 = Expression.Variable(type);
            list.Add(Expression.Assign(parameterExpression2, Expression.Convert(parameterExpression, type)));
            list.Add(Expression.Assign(parameterExpression4, Expression.Convert(parameterExpression3, type)));
            if (isDeepClone)
            {
                list.Add(Expression.Call(parameterExpression5, typeof(DeepCloneState).GetMethod("AddKnownRef"), parameterExpression, parameterExpression3));
            }
            List <FieldInfo> list2 = new List <FieldInfo>();
            Type             type2 = type;

            while (!(type2.Name == "ContextBoundObject"))
            {
                list2.AddRange(type2.GetDeclaredFields());
                type2 = type2.BaseType();
                if (!(type2 != (Type)null))
                {
                    break;
                }
            }
            foreach (FieldInfo item in list2)
            {
                if (isDeepClone && !DeepClonerSafeTypes.CanNotCopyType(item.FieldType, null))
                {
                    MethodInfo       method     = item.FieldType.IsValueType() ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal").MakeGenericMethod(item.FieldType) : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal");
                    MemberExpression arg        = Expression.Field(parameterExpression2, item);
                    Expression       expression = Expression.Call(method, arg, parameterExpression5);
                    if (!item.FieldType.IsValueType())
                    {
                        expression = Expression.Convert(expression, item.FieldType);
                    }
                    if (item.IsInitOnly)
                    {
                        MethodInfo privateStaticMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField");
                        list.Add(Expression.Call(privateStaticMethod, Expression.Constant(item), Expression.Convert(parameterExpression4, typeof(object)), Expression.Convert(expression, typeof(object))));
                    }
                    else
                    {
                        list.Add(Expression.Assign(Expression.Field(parameterExpression4, item), expression));
                    }
                }
                else
                {
                    list.Add(Expression.Assign(Expression.Field(parameterExpression4, item), Expression.Field(parameterExpression2, item)));
                }
            }
            list.Add(Expression.Convert(parameterExpression4, typeFromHandle));
            Type delegateType = typeof(Func <, , ,>).MakeGenericType(typeFromHandle, typeFromHandle, typeof(DeepCloneState), typeFromHandle);
            List <ParameterExpression> list3 = new List <ParameterExpression>();

            if (parameterExpression != parameterExpression2)
            {
                list3.Add(parameterExpression2);
            }
            if (parameterExpression3 != parameterExpression4)
            {
                list3.Add(parameterExpression4);
            }
            return(Expression.Lambda(delegateType, Expression.Block(list3, list), parameterExpression, parameterExpression3, parameterExpression5).Compile());
        }