Exemple #1
0
        private static Func <EnumerableLoopBodyCargo, Expression> CloneKeyValuePair(ParameterExpression clone,
                                                                                    ParameterExpression refTrackerParam)
        {
            Func <EnumerableLoopBodyCargo, Expression> loopBody = cargo =>
            {
                var keyExpression   = Expression.Property(Expression.Property(cargo.Enumerator, cargo.EnumeratorType.GetTypeInfo().GetDeclaredProperty("Current")), cargo.KvpType.GetTypeInfo().GetDeclaredProperty("Key"));
                var valueExpression = Expression.Property(Expression.Property(cargo.Enumerator, cargo.EnumeratorType.GetTypeInfo().GetDeclaredProperty("Current")), cargo.KvpType.GetTypeInfo().GetDeclaredProperty("Value"));

                var addExpr = Expression.Call(clone,
                                              DictionaryMih.Add <string, object>(),
                                              keyExpression,
                                              ClassCloner.CallCopyExpression(valueExpression,
                                                                             refTrackerParam,
                                                                             Expression.Call(valueExpression, ObjectMih.GetTypeMethod())));
                var addNullExpr = Expression.Call(clone,
                                                  DictionaryMih.Add <string, object>(),
                                                  keyExpression,
                                                  Expression.Constant(null));

                return(Expression.IfThenElse(Expression.NotEqual(valueExpression, Expression.Constant(null)),
                                             addExpr,
                                             addNullExpr));
            };

            return(loopBody);
        }
Exemple #2
0
        private static Expression GenerateJaggedArray(List <ParameterExpression> variables,
                                                      ParameterExpression source,
                                                      ParameterExpression clone,
                                                      Type sourceType,
                                                      ParameterExpression refTrackerParam)
        {
            var elementType = sourceType.GetElementType();

            var item       = Expression.Parameter(elementType, "item");
            var clonedItem = Expression.Parameter(elementType, "item");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var i          = Expression.Parameter(typeof(int), "i");
            var length     = Expression.Parameter(typeof(int), "length");

            variables.Add(typeExpr);
            variables.Add(clonedItem);
            variables.Add(item);
            variables.Add(length);
            variables.Add(i);

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Assign(length, Expression.Property(source, "Length")));
            notTrackedExpressions.Add(Expression.Assign(i, Expression.Constant(0)));
            notTrackedExpressions.Add(Expression.Assign(clone, Expression.Convert(Expression.New(sourceType.GetConstructor(new[] { typeof(int) }), length), sourceType)));
            notTrackedExpressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone));

            Debug.Assert(!elementType.IsPrimitive && !elementType.IsValueType && elementType != typeof(string), "Element type cannot be a primitive type");

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(source, ArrayMih.GetValue(), i), elementType)));
            loopExpressions.Add(ClassCloner.GetCloneClassTypeExpression(refTrackerParam, item, clonedItem, elementType));
            loopExpressions.Add(Expression.Call(clone, ArrayMih.SetValue(), Expression.Convert(clonedItem, typeof(object)), i));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond     = Expression.LessThan(i, length);
            var loopBody = Expression.Block(loopExpressions);

            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            notTrackedExpressions.Add(loop);

            return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source,
                                                                         clone,
                                                                         sourceType,
                                                                         refTrackerParam,
                                                                         Expression.Block(notTrackedExpressions)));
        }
Exemple #3
0
        private static Func <EnumerableLoopBodyCargo, Expression> GetLoopBodyCargo(ParameterExpression siClone, ParameterExpression clonedItem, ParameterExpression refTrackerParam)
        {
            Func <EnumerableLoopBodyCargo, Expression> loopBody = cargo =>
            {
                var keyExpression   = Expression.Property(Expression.Property(cargo.Enumerator, cargo.EnumeratorType.GetProperty("Current")), cargo.KvpType.GetProperty("Name"));
                var valueExpression = Expression.Property(Expression.Property(cargo.Enumerator, cargo.EnumeratorType.GetProperty("Current")), cargo.KvpType.GetProperty("Value"));
                var cloneValueExpr  = Expression.Block(ClassCloner.GetCloneClassTypeExpression(refTrackerParam, valueExpression, clonedItem, typeof(object)),
                                                       Expression.Call(siClone, SerializationInfoMih.AddValue(), keyExpression, clonedItem));

                return(Expression.IfThenElse(Expression.Equal(valueExpression, Expression.Constant(null)),
                                             Expression.Call(siClone, SerializationInfoMih.AddValue(), keyExpression, Expression.Constant((object)null, typeof(object))),
                                             cloneValueExpr));
            };

            return(loopBody);
        }
Exemple #4
0
        private static Expression CloneDictionaryWithCustomComparer(Type genericDictionaryType,
                                                                    ConstructorInfo comparerConstructor,
                                                                    List <ParameterExpression> variables,
                                                                    ParameterExpression source,
                                                                    ParameterExpression clone,
                                                                    Type sourceType,
                                                                    ParameterExpression refTrackerParam)
        {
            if (comparerConstructor == null)
            {
                throw new MissingConstructorException("Type " + sourceType + " must have a public constructor that takes an IEqualityComparer<> parameter.");
            }

            var expressions    = new List <Expression>();
            var sourceComparer = Expression.Property(source, nameof(Dictionary <int, int> .Comparer));
            var comparerType   = typeof(IEqualityComparer <>).MakeGenericType(genericDictionaryType.GetGenericArguments()[0]);
            var clonedComparer = ClassCloner.CallCopyExpression(sourceComparer,
                                                                refTrackerParam,
                                                                Expression.Constant(comparerType));

            expressions.Add(Expression.Assign(clone, Expression.New(comparerConstructor, Expression.Convert(clonedComparer, comparerType))));
            expressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone));

            CopyFieldsAndValues(genericDictionaryType,
                                source,
                                clone,
                                sourceType,
                                refTrackerParam,
                                expressions,
                                variables);

            return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source,
                                                                         clone,
                                                                         sourceType,
                                                                         refTrackerParam,
                                                                         Expression.Block(expressions)));
        }
Exemple #5
0
        private static IEnumerable <Expression> GenerateCopyDimensionalArray(ParameterExpression sourceArray,
                                                                             ParameterExpression cloneArray,
                                                                             Type sourceType,
                                                                             List <ParameterExpression> variables,
                                                                             ParameterExpression lengths,
                                                                             int rank,
                                                                             ParameterExpression refTrackerParam)
        {
            var elementType = sourceType.GetElementType();

            var item       = Expression.Parameter(elementType, "item");
            var clonedItem = Expression.Parameter(elementType, "clonedItem");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var indices    = Expression.Parameter(typeof(int[]), "indices");

            variables.Add(typeExpr);
            variables.Add(item);
            variables.Add(indices);
            variables.Add(clonedItem);

            var expressions = new List <Expression>();

            expressions.Add(Expression.Assign(indices, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Constant(rank))));

            Debug.Assert(!(elementType.IsPrimitive || elementType.IsValueType || elementType == typeof(string)), "This method is not made to handle primitive types");

            Expression innerExpression = Expression.Block(ClassCloner.GetCloneClassTypeExpression(refTrackerParam, item, clonedItem, elementType),
                                                          Expression.Call(cloneArray, ArrayMih.SetValueRank(), Expression.Convert(clonedItem, typeof(object)), indices));

            Func <int, Expression, Expression> makeArrayLoop = (loopRank,
                                                                innerExpr) =>
            {
                var loopRankIndex = Expression.Parameter(typeof(int), "loopRankIndex" + loopRank);
                variables.Add(loopRankIndex);

                var loopExpressions = new List <Expression>();

                loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(indices, Expression.Constant(loopRank)), loopRankIndex));
                loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(sourceArray, ArrayMih.GetValueRank(), indices), elementType)));
                loopExpressions.Add(innerExpr);
                loopExpressions.Add(Expression.Assign(loopRankIndex, Expression.Add(loopRankIndex, Expression.Constant(1))));

                var cond     = Expression.LessThan(loopRankIndex, Expression.ArrayIndex(lengths, Expression.Constant(loopRank)));
                var loopBody = Expression.Block(loopExpressions);

                var breakLabel = Expression.Label("breakLabel" + loopRank);
                var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                       loopBody,
                                                                       Expression.Break(breakLabel)),
                                                 breakLabel);
                return(Expression.Block(Expression.Assign(loopRankIndex, Expression.Constant(0)),
                                        loop));
            };

            for (int r = rank - 1; r >= 0; r--)
            {
                innerExpression = makeArrayLoop(r, innerExpression);
            }

            expressions.Add(innerExpression);

            return(expressions);
        }
Exemple #6
0
        private static void CopyFieldsAndValues(Type genericDictionaryType,
                                                ParameterExpression source,
                                                ParameterExpression clone,
                                                Type sourceType,
                                                ParameterExpression refTrackerParam,
                                                List <Expression> expressions,
                                                List <ParameterExpression> variables)
        {
            var clonedItem = Expression.Parameter(typeof(object), "clonedItem");

            variables.Add(clonedItem);

            var fields = InternalSerializationStuff.GetFields(sourceType,
                                                              genericDictionaryType);

            ClassCloner.GenerateCopyFieldsExpressions(fields,
                                                      source,
                                                      clone,
                                                      expressions,
                                                      refTrackerParam,
                                                      clonedItem);

            var typeKey   = genericDictionaryType.GenericTypeArguments[0];
            var typeValue = genericDictionaryType.GenericTypeArguments[1];

            if (IsPrimitive(typeKey) &&
                IsPrimitive(typeValue))
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyPrimitiveKeyAndPrimitiveValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone));
            }
            else if (!IsPrimitive(typeKey) &&
                     IsPrimitive(typeValue))
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyObjectKeyAndPrimitiveValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone,
                                                refTrackerParam));
            }
            else if (IsPrimitive(typeKey) &&
                     !IsPrimitive(typeValue))
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyPrivitiveKeyAndObjectValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone,
                                                refTrackerParam));
            }
            else
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyObjectKeyAndObjectValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone,
                                                refTrackerParam));
            }
        }