Beispiel #1
0
        private static object DeepClone(object srcObject, Dictionary <object, object> visited, bool checkType = true)
        {
            object existing;

            if (visited.TryGetValue(srcObject, out existing))
            {
                return(existing);
            }
            var srcType = srcObject.GetType();

            // FOR DEEP TREES OR COLLECTIONS OF SAME TYPE
            if (null == lastTypeUsed || lastTypeUsed.Type != srcType)
            {
                lastTypeUsed = GetTypeInfos(srcType);
            }
            var typeCache = lastTypeUsed ?? GetTypeInfos(srcObject.GetType());

            return(typeCache.CopyMethod(srcObject, visited));
        }
Beispiel #2
0
        private static TypeCahce GetTypeInfos(Type srcType)
        {
            TypeCahce result;

            if (!typeCache.TryGetValue(srcType, out result))
            {
                result = new TypeCahce()
                {
                    Type = srcType, IsValueType = srcType.IsValueType
                };

                ParameterExpression inputExpr = Expression.Parameter(TYPE_OBJECT);
                var visitedParam = Expression.Parameter(TYPE_DICT_OBJ_OBJ);

                if (!srcType.IsValueType && !srcType.IsArray && srcType.GetConstructor(Type.EmptyTypes) == null)
                {
                    result.CopyMethod = Expression.Lambda <Func <object, Dictionary <object, object>, object> >(
                        Expression.Constant(null, srcType), inputExpr, visitedParam).Compile();
                    typeCache.Add(srcType, result);
                    return(result);
                }

                var memberwiseCloneExpr = Expression.Call(inputExpr, memberwiseClone);
                var resultVar           = Expression.Variable(srcType);
                var srcVar = Expression.Variable(srcType);

                var copyExpressions = new List <Expression>();
                var copyVariables   = new List <ParameterExpression>()
                {
                    resultVar, srcVar
                };

                copyExpressions.Add(Expression.Assign(srcVar, Expression.Convert(inputExpr, srcType)));
                copyExpressions.Add(Expression.Assign(resultVar, Expression.Convert(memberwiseCloneExpr, srcType)));
                //copyExpressions.Add(Expression.Assign(resultVar, Expression.Convert(Expression.New(srcType), srcType)));


                if (srcType.IsArray)
                {
                    var arrCopyExpr = Expression.Assign(resultVar,
                                                        Expression.Convert(Expression.Call(thisArrayClone, Expression.Convert(srcVar, TYPE_ARRAY), visitedParam), srcType));
                    copyExpressions.Add(arrCopyExpr);
                }
                else if (TYPE_ICOLLECTION.IsAssignableFrom(srcType) && srcType.IsGenericType)
                {
                    var listCopyExpr = Expression.Assign(resultVar,
                                                         Expression.Convert(Expression.Call(thisCollectionClone, Expression.Convert(srcVar, TYPE_ICOLLECTION), visitedParam), srcType));
                    copyExpressions.Add(listCopyExpr);
                }
                else
                {
                    copyExpressions.Add(Expression.Assign(Expression.Property(visitedParam,
                                                                              TYPE_DICT_OBJ_OBJ.GetProperty("Item"), inputExpr), Expression.Convert(resultVar, TYPE_OBJECT)));
                    BuildPropertiesExpression(result, srcType, srcVar, resultVar, visitedParam, copyExpressions);
                }

                copyExpressions.Add(Expression.Convert(resultVar, TYPE_OBJECT));
                var copyExpr = Expression.Lambda <Func <object, Dictionary <object, object>, object> >(
                    Expression.Block(copyVariables, copyExpressions), inputExpr, visitedParam).Compile();

                result.CopyMethod = copyExpr;

                typeCache.Add(srcType, result);
                return(result);
            }

            return(result);
        }
Beispiel #3
0
 private static void BuildPropertiesExpression(TypeCahce result,
                                               Type srcType,
                                               ParameterExpression srcVar,
                                               ParameterExpression resultVar,
                                               ParameterExpression visitedParam,
                                               List <Expression> copyExpressions
                                               )
 {
     foreach (var eachField in srcType.GetFields(BindingFlags.Public | BindingFlags.Instance))
     {
         var mode = GetAttrMode(eachField);
         if (mode != CloningMode.Shallow)
         {
             var fldCopyTo = Expression.Field(resultVar, eachField);
             if (mode == CloningMode.Deep)
             {
                 if (!IsPrimitive(eachField.FieldType))
                 {
                     bool needtToCheck = NeedToCheckType(eachField.FieldType);
                     var  fldCopyFrom  = Expression.Field(srcVar, eachField);
                     var  chekType     = Expression.Constant(needtToCheck, TYPE_BOOL);
                     var  fldCopyExpr  = Expression.Assign(fldCopyTo,
                                                           Expression.Convert(Expression.Call(thisClone, Expression.Convert(fldCopyFrom, TYPE_OBJECT), visitedParam, chekType), eachField.FieldType));
                     if (eachField.FieldType.IsValueType)
                     {
                         copyExpressions.Add(fldCopyExpr);
                     }
                     else
                     {
                         var copyIfNotNull = Expression.IfThen(Expression.NotEqual(fldCopyFrom, Expression.Constant(null, eachField.FieldType)), fldCopyExpr);
                         if (needtToCheck)
                         {
                             // todo: add more type checks
                             copyExpressions.Add(Expression.IfThen(Expression.Not(Expression.TypeEqual(fldCopyFrom, TYPE_INT)), copyIfNotNull));
                         }
                         else
                         {
                             copyExpressions.Add(copyIfNotNull);
                         }
                     }
                 }
             }
             else //if (mode == CloningMode.Ignore)
             {
                 copyExpressions.Add(Expression.Assign(fldCopyTo, Expression.Default(eachField.FieldType)));
             }
         }
     }
     foreach (var eachProp in srcType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
     {
         if (!eachProp.CanWrite)
         {
             continue;
         }
         var mode = GetAttrMode(eachProp);
         if (mode != CloningMode.Shallow)
         {
             var propCopyTo = Expression.Property(resultVar, eachProp);
             if (mode == CloningMode.Deep)
             {
                 if (!IsPrimitive(eachProp.PropertyType))
                 {
                     bool needtToCheck = NeedToCheckType(eachProp.PropertyType);
                     var  chekType     = Expression.Constant(needtToCheck, TYPE_BOOL);
                     var  propCopyFrom = Expression.Property(srcVar, eachProp);
                     var  propCopyExpr = Expression.Assign(propCopyTo, Expression.Convert(
                                                               Expression.Call(thisClone, Expression.Convert(propCopyFrom, TYPE_OBJECT), visitedParam, chekType),
                                                               eachProp.PropertyType));
                     if (eachProp.PropertyType.IsValueType)
                     {
                         copyExpressions.Add(propCopyExpr);
                     }
                     else
                     {
                         var copyIfNotNUllExpr = Expression.IfThen(Expression.NotEqual(propCopyFrom, Expression.Constant(null, eachProp.PropertyType)), propCopyExpr);
                         if (needtToCheck)
                         {
                             // todo: add more type checks
                             copyExpressions.Add(Expression.IfThen(Expression.Not(Expression.TypeEqual(propCopyFrom, TYPE_INT)), copyIfNotNUllExpr));
                         }
                         else
                         {
                             copyExpressions.Add(copyIfNotNUllExpr);
                         }
                     }
                 }
             }
             else //if (mode == CloningMode.Ignore)
             {
                 copyExpressions.Add(Expression.Assign(propCopyTo, Expression.Default(eachProp.PropertyType)));
             }
         }
     }
 }