private static object GenerateProcessArrayMethod(Type type)
        {
            Type       elementType = type.GetElementType();
            int        rank        = type.GetArrayRank();
            MethodInfo methodInfo;

            if (rank != 1 || type != elementType.MakeArrayType())
            {
                methodInfo = ((rank != 2 || !(type == elementType.MakeArrayType())) ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneAbstractArrayInternal") : typeof(DeepClonerGenerator).GetPrivateStaticMethod("Clone2DimArrayInternal").MakeGenericMethod(elementType));
            }
            else
            {
                string methodName = "Clone1DimArrayClassInternal";
                if (DeepClonerSafeTypes.CanReturnSameObject(elementType))
                {
                    methodName = "Clone1DimArraySafeInternal";
                }
                else if (elementType.IsValueType())
                {
                    methodName = "Clone1DimArrayStructInternal";
                }
                methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType);
            }
            ParameterExpression  from  = Expression.Parameter(typeof(object));
            ParameterExpression  state = Expression.Parameter(typeof(DeepCloneState));
            MethodCallExpression call  = Expression.Call(methodInfo, Expression.Convert(from, type), state);

            return(Expression.Lambda(typeof(Func <, , >).MakeGenericType(typeof(object), typeof(DeepCloneState), typeof(object)), call, from, state).Compile());
        }
Пример #2
0
        private static object GenerateProcessArrayMethod(Type type, bool isDeep)
        {
            Type elementType          = type.GetElementType();
            int  rank                 = type.GetArrayRank();
            ParameterExpression from  = Expression.Parameter(typeof(object));
            ParameterExpression to    = Expression.Parameter(typeof(object));
            ParameterExpression state = Expression.Parameter(typeof(DeepCloneState));
            Type funcType             = typeof(Func <, , , >).MakeGenericType(typeof(object), typeof(object), typeof(DeepCloneState), typeof(object));

            if (rank == 1 && type == elementType.MakeArrayType())
            {
                if (!isDeep)
                {
                    MethodCallExpression callS3 = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod("ShallowClone1DimArraySafeInternal").MakeGenericMethod(elementType), Expression.Convert(from, type), Expression.Convert(to, type));
                    return(Expression.Lambda(funcType, callS3, from, to, state).Compile());
                }
                string methodName = "Clone1DimArrayClassInternal";
                if (DeepClonerSafeTypes.CanReturnSameObject(elementType))
                {
                    methodName = "Clone1DimArraySafeInternal";
                }
                else if (elementType.IsValueType())
                {
                    methodName = "Clone1DimArrayStructInternal";
                }
                MethodCallExpression callS2 = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType), Expression.Convert(from, type), Expression.Convert(to, type), state);
                return(Expression.Lambda(funcType, callS2, from, to, state).Compile());
            }
            MethodCallExpression callS = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod((rank == 2 && type == elementType.MakeArrayType()) ? "Clone2DimArrayInternal" : "CloneAbstractArrayInternal"), Expression.Convert(from, type), Expression.Convert(to, type), state, Expression.Constant(isDeep));

            return(Expression.Lambda(funcType, callS, from, to, state).Compile());
        }
Пример #3
0
 private static object GenerateCloner(Type t, bool asObject)
 {
     if (DeepClonerSafeTypes.CanReturnSameObject(t) && asObject && !t.IsValueType())
     {
         return(null);
     }
     if (ShallowObjectCloner.IsSafeVariant())
     {
         return(DeepClonerExprGenerator.GenerateClonerInternal(t, asObject));
     }
     return(DeepClonerMsilGenerator.GenerateClonerInternal(t, asObject));
 }
Пример #4
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep)
        {
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            int l3 = Math.Min(objFrom.GetLength(0), objTo.GetLength(0));
            int 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 (int n = 0; n < l3; n++)
                {
                    for (int m = 0; m < l2; m++)
                    {
                        objTo[n, m] = objFrom[n, m];
                    }
                }
                return(objTo);
            }
            if (typeof(T).IsValueType())
            {
                Func <T, DeepCloneState, T> cloner = DeepClonerGenerator.GetClonerForValueType <T>();
                for (int l = 0; l < l3; l++)
                {
                    for (int k = 0; k < l2; k++)
                    {
                        objTo[l, k] = cloner(objFrom[l, k], state);
                    }
                }
            }
            else
            {
                for (int j = 0; j < l3; j++)
                {
                    for (int i = 0; i < l2; i++)
                    {
                        objTo[j, i] = (T)DeepClonerGenerator.CloneClassInternal(objFrom[j, i], state);
                    }
                }
            }
            return(objTo);
        }
Пример #5
0
 public static T CloneObject <T>(T obj)
 {
     if (obj is ValueType)
     {
         Type type = obj.GetType();
         if (typeof(T) == type)
         {
             if (DeepClonerSafeTypes.CanReturnSameObject(type))
             {
                 return(obj);
             }
             return(CloneStructInternal(obj, new DeepCloneState()));
         }
     }
     return((T)CloneClassRoot(obj));
 }
Пример #6
0
 public static T CloneObject <T>(T obj)
 {
     if (obj is ValueType)
     {
         if (typeof(T) == obj.GetType())
         {
             return(obj);
         }
         return((T)ShallowObjectCloner.CloneObject(obj));
     }
     if (obj == null)
     {
         return((T)(object)null);
     }
     if (DeepClonerSafeTypes.CanReturnSameObject(obj.GetType()))
     {
         return(obj);
     }
     return((T)ShallowObjectCloner.CloneObject(obj));
 }
Пример #7
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }
            int l3 = obj.GetLength(0);
            int l2 = obj.GetLength(1);

            T[,] outArray = new T[l3, l2];
            state.AddKnownRef(obj, outArray);
            if (DeepClonerSafeTypes.CanReturnSameObject(typeof(T)))
            {
                Array.Copy(obj, outArray, obj.Length);
                return(outArray);
            }
            if (typeof(T).IsValueType())
            {
                Func <T, DeepCloneState, T> cloner = GetClonerForValueType <T>();
                for (int l = 0; l < l3; l++)
                {
                    for (int k = 0; k < l2; k++)
                    {
                        outArray[l, k] = cloner(obj[l, k], state);
                    }
                }
            }
            else
            {
                for (int j = 0; j < l3; j++)
                {
                    for (int i = 0; i < l2; i++)
                    {
                        outArray[j, i] = (T)CloneClassInternal(obj[j, i], state);
                    }
                }
            }
            return(outArray);
        }
Пример #8
0
        private static void GenerateProcessMethod(ILGenerator il, Type type, bool unboxStruct)
        {
            if (type.IsArray)
            {
                GenerateProcessArrayMethod(il, type);
                return;
            }
            if (type.FullName != null && type.FullName.StartsWith("System.Tuple`"))
            {
                Type[] genericArguments = type.GenericArguments();
                if (genericArguments.Length < 10 && genericArguments.All(DeepClonerSafeTypes.CanReturnSameObject))
                {
                    GenerateProcessTupleMethod(il, type);
                    return;
                }
            }
            LocalBuilder typeLocal         = il.DeclareLocal(type);
            LocalBuilder structLoc         = null;
            bool         isGoodConstructor = false;

            if (!type.IsValueType)
            {
                ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
                isGoodConstructor = DeepClonerMsilHelper.IsConstructorDoNothing(type, constructor);
                if (isGoodConstructor)
                {
                    il.Emit(OpCodes.Newobj, constructor);
                }
                else
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Call, typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic));
                }
                il.Emit(OpCodes.Stloc, typeLocal);
            }
            else if (unboxStruct)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Unbox_Any, type);
                structLoc = il.DeclareLocal(type);
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Stloc, structLoc);
                il.Emit(OpCodes.Stloc, typeLocal);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Stloc, typeLocal);
            }
            if (type.IsClass)
            {
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc, typeLocal);
                il.Emit(OpCodes.Call, typeof(DeepCloneState).GetMethod("AddKnownRef"));
            }
            List <FieldInfo> fi = new List <FieldInfo>();
            Type             tp = type;

            while (!(tp == typeof(ContextBoundObject)))
            {
                fi.AddRange(tp.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
                tp = tp.BaseType;
                if (!(tp != null))
                {
                    break;
                }
            }
            foreach (FieldInfo fieldInfo in fi)
            {
                if (DeepClonerSafeTypes.CanReturnSameObject(fieldInfo.FieldType))
                {
                    if (isGoodConstructor)
                    {
                        il.Emit(type.IsClass ? OpCodes.Ldloc : OpCodes.Ldloca_S, typeLocal);
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldfld, fieldInfo);
                        il.Emit(OpCodes.Stfld, fieldInfo);
                    }
                    continue;
                }
                il.Emit(type.IsClass ? OpCodes.Ldloc : OpCodes.Ldloca_S, typeLocal);
                if (structLoc == null)
                {
                    il.Emit(OpCodes.Ldarg_0);
                }
                else
                {
                    il.Emit(OpCodes.Ldloc, structLoc);
                }
                il.Emit(OpCodes.Ldfld, fieldInfo);
                il.Emit(OpCodes.Ldarg_1);
                MethodInfo methodInfo = (fieldInfo.FieldType.IsValueType ? typeof(DeepClonerGenerator).GetMethod("CloneStructInternal", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType) : typeof(DeepClonerGenerator).GetMethod("CloneClassInternal", BindingFlags.Static | BindingFlags.NonPublic));
                il.Emit(OpCodes.Call, methodInfo);
                il.Emit(OpCodes.Stfld, fieldInfo);
            }
            il.Emit(OpCodes.Ldloc, typeLocal);
            if (unboxStruct)
            {
                il.Emit(OpCodes.Box, type);
            }
            il.Emit(OpCodes.Ret);
        }
Пример #9
0
        private static void GenerateProcessArrayMethod(ILGenerator il, Type type)
        {
            Type elementType = type.GetElementType();
            int  rank        = type.GetArrayRank();

            if (rank != 1 || type != elementType.MakeArrayType())
            {
                MethodInfo methodInfo = ((rank != 2 || !(type == elementType.MakeArrayType())) ? typeof(DeepClonerGenerator).GetMethod("CloneAbstractArrayInternal", BindingFlags.Static | BindingFlags.NonPublic) : typeof(DeepClonerGenerator).GetMethod("Clone2DimArrayInternal", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(elementType));
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Call, methodInfo);
                il.Emit(OpCodes.Ret);
                return;
            }
            LocalBuilder typeLocal = il.DeclareLocal(type);
            LocalBuilder lenLocal  = il.DeclareLocal(typeof(int));

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, type.GetProperty("Length").GetGetMethod());
            il.Emit(OpCodes.Dup);
            il.Emit(OpCodes.Stloc, lenLocal);
            il.Emit(OpCodes.Newarr, elementType);
            il.Emit(OpCodes.Stloc, typeLocal);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc, typeLocal);
            il.Emit(OpCodes.Call, typeof(DeepCloneState).GetMethod("AddKnownRef"));
            if (DeepClonerSafeTypes.CanReturnSameObject(elementType))
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc, typeLocal);
                il.Emit(OpCodes.Ldloc, lenLocal);
                il.Emit(OpCodes.Call, typeof(Array).GetMethod("Copy", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
                {
                    typeof(Array),
                    typeof(Array),
                    typeof(int)
                }, null));
            }
            else
            {
                MethodInfo   methodInfo2 = (elementType.IsValueType ? typeof(DeepClonerGenerator).GetMethod("CloneStructInternal", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(elementType) : typeof(DeepClonerGenerator).GetMethod("CloneClassInternal", BindingFlags.Static | BindingFlags.NonPublic));
                LocalBuilder clonerLocal = null;
                if (type.IsValueType)
                {
                    Type funcType = typeof(Func <, , >).MakeGenericType(elementType, typeof(DeepCloneState), elementType);
                    methodInfo2 = funcType.GetMethod("Invoke");
                    clonerLocal = il.DeclareLocal(funcType);
                    il.Emit(OpCodes.Call, typeof(DeepClonerGenerator).GetMethod("GetClonerForValueType", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(elementType));
                    il.Emit(OpCodes.Stloc, clonerLocal);
                }
                Label        endLoopLabel   = il.DefineLabel();
                Label        startLoopLabel = il.DefineLabel();
                LocalBuilder iLocal         = il.DeclareLocal(typeof(int));
                il.Emit(OpCodes.Ldc_I4_0);
                il.Emit(OpCodes.Stloc, iLocal);
                il.MarkLabel(startLoopLabel);
                il.Emit(OpCodes.Ldloc, iLocal);
                il.Emit(OpCodes.Ldloc, lenLocal);
                il.Emit(OpCodes.Bge_S, endLoopLabel);
                il.Emit(OpCodes.Ldloc, typeLocal);
                il.Emit(OpCodes.Ldloc, iLocal);
                if (clonerLocal != null)
                {
                    il.Emit(OpCodes.Ldloc, clonerLocal);
                }
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc, iLocal);
                il.Emit(OpCodes.Ldelem, elementType);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Call, methodInfo2);
                il.Emit(OpCodes.Stelem, elementType);
                il.Emit(OpCodes.Ldloc, iLocal);
                il.Emit(OpCodes.Ldc_I4_1);
                il.Emit(OpCodes.Add);
                il.Emit(OpCodes.Stloc, iLocal);
                il.Emit(OpCodes.Br_S, startLoopLabel);
                il.MarkLabel(endLoopLabel);
            }
            il.Emit(OpCodes.Ldloc, typeLocal);
            il.Emit(OpCodes.Ret);
        }
        private static object GenerateProcessMethod(Type type, bool unboxStruct)
        {
            if (type.IsArray)
            {
                return(GenerateProcessArrayMethod(type));
            }
            if (type.FullName != null && type.FullName.StartsWith("System.Tuple`"))
            {
                Type[] genericArguments = type.GenericArguments();
                if (genericArguments.Length < 10 && genericArguments.All(DeepClonerSafeTypes.CanReturnSameObject))
                {
                    return(GenerateProcessTupleMethod(type));
                }
            }
            Type methodType = ((unboxStruct || type.IsClass()) ? typeof(object) : type);
            List <Expression>   expressionList = new List <Expression>();
            ParameterExpression from           = Expression.Parameter(methodType);
            ParameterExpression fromLocal      = from;
            ParameterExpression toLocal        = Expression.Variable(type);
            ParameterExpression state          = Expression.Parameter(typeof(DeepCloneState));

            if (!type.IsValueType())
            {
                MethodInfo methodInfo = typeof(object).GetPrivateMethod("MemberwiseClone");
                expressionList.Add(Expression.Assign(toLocal, Expression.Convert(Expression.Call(from, methodInfo), type)));
                fromLocal = Expression.Variable(type);
                expressionList.Add(Expression.Assign(fromLocal, Expression.Convert(from, type)));
                expressionList.Add(Expression.Call(state, typeof(DeepCloneState).GetMethod("AddKnownRef"), from, toLocal));
            }
            else if (unboxStruct)
            {
                expressionList.Add(Expression.Assign(toLocal, Expression.Unbox(from, type)));
                fromLocal = Expression.Variable(type);
                expressionList.Add(Expression.Assign(fromLocal, toLocal));
            }
            else
            {
                expressionList.Add(Expression.Assign(toLocal, from));
            }
            List <FieldInfo> fi = new List <FieldInfo>();
            Type             tp = type;

            while (!(tp == typeof(ContextBoundObject)))
            {
                fi.AddRange(tp.GetDeclaredFields());
                tp = tp.BaseType();
                if (!(tp != null))
                {
                    break;
                }
            }
            foreach (FieldInfo fieldInfo in fi)
            {
                if (!DeepClonerSafeTypes.CanReturnSameObject(fieldInfo.FieldType))
                {
                    MethodInfo       method = (fieldInfo.FieldType.IsValueType() ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal").MakeGenericMethod(fieldInfo.FieldType) : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal"));
                    MemberExpression get    = Expression.Field(fromLocal, fieldInfo);
                    Expression       call   = Expression.Call(method, get, state);
                    if (!fieldInfo.FieldType.IsValueType())
                    {
                        call = Expression.Convert(call, fieldInfo.FieldType);
                    }
                    if (_readonlyFields.GetOrAdd(fieldInfo, (FieldInfo f) => f.IsInitOnly))
                    {
                        MethodInfo 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));
            Type delegateType = typeof(Func <, , >).MakeGenericType(methodType, typeof(DeepCloneState), methodType);
            List <ParameterExpression> blockParams = new List <ParameterExpression>();

            if (from != fromLocal)
            {
                blockParams.Add(fromLocal);
            }
            blockParams.Add(toLocal);
            return(Expression.Lambda(delegateType, Expression.Block(blockParams, expressionList), from, state).Compile());
        }
Пример #11
0
        private static object GenerateProcessMethod(Type type, bool isDeepClone)
        {
            if (type.IsArray)
            {
                return(GenerateProcessArrayMethod(type, isDeepClone));
            }
            Type methodType = typeof(object);
            List <Expression>   expressionList = new List <Expression>();
            ParameterExpression from           = Expression.Parameter(methodType);
            ParameterExpression fromLocal2     = from;
            ParameterExpression to             = Expression.Parameter(methodType);
            ParameterExpression toLocal2       = to;
            ParameterExpression state          = Expression.Parameter(typeof(DeepCloneState));

            fromLocal2 = Expression.Variable(type);
            toLocal2   = Expression.Variable(type);
            expressionList.Add(Expression.Assign(fromLocal2, Expression.Convert(from, type)));
            expressionList.Add(Expression.Assign(toLocal2, Expression.Convert(to, type)));
            if (isDeepClone)
            {
                expressionList.Add(Expression.Call(state, typeof(DeepCloneState).GetMethod("AddKnownRef"), from, to));
            }
            List <FieldInfo> fi = new List <FieldInfo>();
            Type             tp = type;

            while (!(tp == typeof(ContextBoundObject)))
            {
                fi.AddRange(tp.GetDeclaredFields());
                tp = tp.BaseType();
                if (!(tp != null))
                {
                    break;
                }
            }
            foreach (FieldInfo fieldInfo in fi)
            {
                if (isDeepClone && !DeepClonerSafeTypes.CanReturnSameObject(fieldInfo.FieldType))
                {
                    MethodInfo       method = fieldInfo.FieldType.IsValueType() ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal").MakeGenericMethod(fieldInfo.FieldType) : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal");
                    MemberExpression get    = Expression.Field(fromLocal2, fieldInfo);
                    Expression       call   = Expression.Call(method, get, state);
                    if (!fieldInfo.FieldType.IsValueType())
                    {
                        call = Expression.Convert(call, fieldInfo.FieldType);
                    }
                    if (fieldInfo.IsInitOnly)
                    {
                        MethodInfo setMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField");
                        expressionList.Add(Expression.Call(setMethod, Expression.Constant(fieldInfo), Expression.Convert(toLocal2, typeof(object)), Expression.Convert(call, typeof(object))));
                    }
                    else
                    {
                        expressionList.Add(Expression.Assign(Expression.Field(toLocal2, fieldInfo), call));
                    }
                }
                else
                {
                    expressionList.Add(Expression.Assign(Expression.Field(toLocal2, fieldInfo), Expression.Field(fromLocal2, fieldInfo)));
                }
            }
            expressionList.Add(Expression.Convert(toLocal2, methodType));
            Type delegateType = typeof(Func <, , , >).MakeGenericType(methodType, methodType, typeof(DeepCloneState), methodType);
            List <ParameterExpression> blockParams = new List <ParameterExpression>();

            if (from != fromLocal2)
            {
                blockParams.Add(fromLocal2);
            }
            if (to != toLocal2)
            {
                blockParams.Add(toLocal2);
            }
            return(Expression.Lambda(delegateType, Expression.Block(blockParams, expressionList), from, to, state).Compile());
        }