Ejemplo n.º 1
0
        public void Replace(MethodDefinition targetMethod)
        {
            var replacer = new MethodReplacer(targetMethod.Body);

            replacer.RemoveSection();
            replacer.Replace(method);
        }
Ejemplo n.º 2
0
        private static IEnumerable <Expression> GetArrays(Type rootType, Expression path, IEnumerable <MutatorConfiguration> mutators)
        {
            var arrays          = new List <Dictionary <Type, List <Expression> > >();
            var arraysExtractor = new ArraysExtractor(arrays);

            arraysExtractor.GetArrays(path);
            foreach (var mutator in mutators)
            {
                mutator.GetArrays(arraysExtractor);
            }
            var result   = new List <Expression>();
            var replacer = new MethodReplacer(MutatorsHelperFunctions.CurrentMethod, MutatorsHelperFunctions.EachMethod);

            for (var i = 1; i < arrays.Count; ++i)
            {
                var dict = arrays[i];
                if (dict.Count > 1)
                {
                    throw new InvalidOperationException("Too many root types");
                }
                List <Expression> list;
                if (!dict.TryGetValue(rootType, out list))
                {
                    throw new InvalidOperationException("Invalid root type");
                }
                var arraysOfCurrentLevel = list.GroupBy(exp => new ExpressionWrapper(replacer.Visit(exp), false)).Select(grouping => grouping.First()).ToArray();
                if (arraysOfCurrentLevel.Length > 1)
                {
                    throw new NotSupportedException("Iteration over more than one array is not supported");
                }
                result.Add(arraysOfCurrentLevel[0]);
            }

            return(result);
        }
Ejemplo n.º 3
0
        public void TestMethod_RetVoid_ArgInt()
        {
            //Assign

            var state          = 4;
            var targetMethod   = typeof(A_RetVoid_ArgInt).GetMethod(nameof(A_RetVoid_ArgInt.Execute));
            var injectedMethod = typeof(A_RetVoid_ArgInt).GetMethod(nameof(A_RetVoid_ArgInt.ExecuteWithStateChange));

            var a = new A_RetVoid_ArgInt();

            a.Execute(state);
            var oldState = a.State;

            //Act

            MethodReplacer.Replace(targetMethod, injectedMethod);
            a.Execute(state);

            //Assert

            var newState = a.State;

            Assert.AreEqual(oldState, 0);
            Assert.AreEqual(newState, state);
        }
Ejemplo n.º 4
0
 public static Expression RemoveLinqFirstAndSingle(this Expression expression)
 {
     expression = new MethodReplacer(firstWithoutParametersMethod, firstOrDefaultWithoutParametersMethod).Visit(expression);
     expression = new MethodReplacer(firstWithParametersMethod, firstOrDefaultWithParametersMethod).Visit(expression);
     expression = new MethodReplacer(singleWithoutParametersMethod, singleOrDefaultWithoutParametersMethod).Visit(expression);
     expression = new MethodReplacer(singleWithParametersMethod, singleOrDefaultWithParametersMethod).Visit(expression);
     return(expression);
 }
        public void DynamicMethodCreatorTestCreate()
        {
            var targetMethod   = typeof(A).GetMethod(nameof(A.Execute));
            var injectedMethod = DynamicMethodCreator.DynamicMethodCreator.CreateMethodSameAsOrigial(targetMethod);

            MethodReplacer.Replace(targetMethod, injectedMethod);

            new A().Execute();
        }
        public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TTarget> Set <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TTarget>(
            this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TTarget> configurator,
            Expression <Func <TSourceChild, TTarget> > value)
        {
            var methodReplacer             = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToSourceChild          = (Expression <Func <TSourceRoot, TSourceChild> >)methodReplacer.Visit(configurator.PathToSourceChild);
            LambdaExpression valueFromRoot = pathToSourceChild.Merge(value);

            configurator.SetMutator(EqualsToConfiguration.Create(typeof(TDestRoot), valueFromRoot, null));
            return(configurator);
        }
        public static MutatorsConfigurator <TRoot, TChild, TValue> Required <TRoot, TChild, TValue>(
            this MutatorsConfigurator <TRoot, TChild, TValue> configurator,
            Expression <Func <TChild, TValue, MultiLanguageTextBase> > message,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToValue    = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue);
            var pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);

            configurator.SetMutator(RequiredIfConfiguration.Create(MutatorsCreator.Sharp, priority, null, pathToValue, message.Merge(pathToChild, pathToValue), type));
            return(configurator);
        }
        public static MutatorsConfigurator <TRoot, TChild, string> IsLike <TRoot, TChild>(
            this MutatorsConfigurator <TRoot, TChild, string> configurator,
            string pattern,
            Expression <Func <TChild, MultiLanguageTextBase> > message,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToValue    = (Expression <Func <TRoot, string> >)methodReplacer.Visit(configurator.PathToValue);
            var pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);

            configurator.SetMutator(RegexValidatorConfiguration.Create(MutatorsCreator.Sharp, priority, pathToValue, null, pathToChild.Merge(message), pattern, type));
            return(configurator);
        }
        protected StaticValidatorConfiguration(Type type, MutatorsCreator creator, string name, int priority,
                                               LambdaExpression condition, LambdaExpression pathToNode, LambdaExpression pathToValue, LambdaExpression validator)
            : base(type, creator, priority)
        {
            Name      = name;
            Condition = condition;
            var replacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);

            PathToNode        = (LambdaExpression)replacer.Visit(pathToNode);
            PathToValue       = (LambdaExpression)replacer.Visit(pathToValue);
            validator         = Prepare(validator);
            this.validator    = validator;
            validatorFromRoot = pathToNode.Merge(validator);
        }
        public static MutatorsConfigurator <TRoot, TChild, TValue> MustBeEqualTo <TRoot, TChild, TValue>(
            this MutatorsConfigurator <TRoot, TChild, TValue> configurator,
            Expression <Func <TChild, TValue> > expectedValue,
            Expression <Func <TChild, MultiLanguageTextBase> > message,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToValue    = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue);
            var pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);
            var condition      = Expression.Convert(Expression.NotEqual(pathToValue.ReplaceParameter(pathToChild.Parameters[0]).Body, pathToChild.Merge(expectedValue).Body), typeof(bool?));

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToChild.Parameters), pathToChild.Merge(message), type));
            return(configurator);
        }
        public static MutatorsConfigurator <TRoot, TChild, TValue> IfFilledMustBelongTo <TRoot, TChild, TValue>(
            this MutatorsConfigurator <TRoot, TChild, TValue> configurator,
            IEnumerable <TValue> values,
            Expression <Func <TChild, TValue, MultiLanguageTextBase> > message,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToValue    = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue);
            var pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);
            var contains       = Expression.Call(containsMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body);
            var condition      = Expression.Convert(Expression.AndAlso(Expression.NotEqual(pathToValue.Body, Expression.Constant(null, typeof(TValue))), Expression.Not(contains)), typeof(bool?));

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), message.Merge(pathToChild, pathToValue), type));
            return(configurator);
        }
        public static MutatorsConfigurator <TRoot, TChild, string> LengthExactly <TRoot, TChild>(this MutatorsConfigurator <TRoot, TChild, string> configurator, int length, MultiLanguageTextBase title,
                                                                                                 int priority = 0,
                                                                                                 ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToValue    = (Expression <Func <TRoot, string> >)methodReplacer.Visit(configurator.PathToValue);
            var condition      = Expression.Convert(Expression.NotEqual(Expression.MakeMemberAccess(pathToValue.Body, stringLengthProperty), Expression.Constant(length)), typeof(bool?));
            var message        = Expression.Lambda <Func <TRoot, MultiLanguageTextBase> >(Expression.MemberInit(
                                                                                              Expression.New(typeof(LengthNotExactlyEqualsText)),
                                                                                              Expression.Bind(lengthNotExactlyEqualsTextExacltyProperty, Expression.Constant(length, typeof(int?))),
                                                                                              Expression.Bind(lengthNotExactlyEqualsTextTitleProperty, Expression.Constant(title, typeof(MultiLanguageTextBase))),
                                                                                              Expression.Bind(lengthNotExactlyEqualsTextValueProperty, pathToValue.Body)), pathToValue.Parameters);

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), message, type));
            return(configurator);
        }
Ejemplo n.º 13
0
        public async Task ReplaceStaticMethodFromAnotherClass()
        {
            //Assign

            var state          = 1;
            var targetMethod   = typeof(A).GetMethod(nameof(A.ExecuteStatic));
            var injectedMethod = typeof(B).GetMethod(nameof(B.ExecuteStatic));

            var oldState = await A.ExecuteStatic(state);

            //Act

            MethodReplacer.Replace(targetMethod, injectedMethod);
            var newState = await A.ExecuteStatic(state);

            //Assert

            Assert.AreEqual(oldState, 100);
            Assert.AreEqual(newState, 200);
        }
Ejemplo n.º 14
0
        public async Task ReplaceNonStaticWithStaticUnexpectedBehavior()
        {
            //Assign

            var state          = 1;
            var targetMethod   = typeof(A_UB).GetMethod(nameof(A_UB.ExecuteStatic));
            var injectedMethod = typeof(B_UB).GetMethod(nameof(B_UB.Execute));

            var oldState = await A_UB.ExecuteStatic(state);

            //Act

            MethodReplacer.Replace(targetMethod, injectedMethod);
            var newState = await A_UB.ExecuteStatic(state);

            //Assert

            Assert.AreEqual(oldState, 100);
            Assert.AreNotEqual(newState, oldState);
            Assert.AreNotEqual(newState, 20);
        }
        public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> Set <TSourceRoot, TSourceChild, TSourceNode, TSourceValue, TDestRoot, TDestChild, TDestValue>(
            this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator,
            Expression <Func <TSourceChild, TSourceNode> > node,
            Expression <Func <TSourceNode, TSourceValue> > value,
            Expression <Func <TSourceValue, TDestValue> > converter,
            Expression <Func <TSourceNode, ValidationResult> > validator,
            int priority = 0)
        {
            var methodReplacer         = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToSourceChild      = (Expression <Func <TSourceRoot, TSourceChild> >)methodReplacer.Visit(configurator.PathToSourceChild);
            var nodeFromRoot           = pathToSourceChild.Merge(node);
            var valueFromRoot          = nodeFromRoot.Merge(value);
            var convertedValue         = converter == null ? (LambdaExpression)valueFromRoot : valueFromRoot.Merge(converter);
            var validatorConfiguration = validator == null
                                             ? null
                                             : StaticValidatorConfiguration.Create(MutatorsCreator.Sharp, "SetWithValidator", priority,
                                                                                   null, nodeFromRoot, valueFromRoot, validator);

            configurator.SetMutator(EqualsToConfiguration.Create(typeof(TDestRoot), convertedValue, validatorConfiguration));
            return(configurator);
        }
        public static MutatorsConfigurator <TRoot, TChild, TValue> MustBeEqualTo <TRoot, TChild, TValue>(
            this MutatorsConfigurator <TRoot, TChild, TValue> configurator,
            Expression <Func <TChild, TValue> > expectedValue,
            IEqualityComparer <TValue> comparer = null,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);
            var pathToValue    = ((Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue)).ReplaceParameter(pathToChild.Parameters[0]).Body;
            var equal          = comparer == null
                            ? (Expression)Expression.Equal(pathToValue, pathToChild.Merge(expectedValue).Body)
                            : Expression.Call(Expression.Constant(comparer, typeof(IEqualityComparer <TValue>)), "Equals", Type.EmptyTypes, pathToValue, pathToChild.Merge(expectedValue).Body);
            var condition = Expression.Convert(Expression.Not(equal), typeof(bool?));
            var message   = Expression.MemberInit(Expression.New(typeof(ValueMustBeEqualToText)),
                                                  Expression.Bind(valueMustBeEqualToTextExpectedValueProperty, Expression.Convert(expectedValue.Body, typeof(object))),
                                                  Expression.Bind(valueMustBeEqualToTextActualValueProperty, Expression.Convert(pathToValue, typeof(object))));

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToChild.Parameters), pathToChild.Merge(Expression.Lambda <Func <TChild, MultiLanguageTextBase> >(message, expectedValue.Parameters)), type));
            return(configurator);
        }
Ejemplo n.º 17
0
        public async Task TestMethod_RetInt_ArgInt_Async()
        {
            //Assign

            var state          = 4;
            var targetMethod   = typeof(A_RetInt_ArgInt_Async).GetMethod(nameof(A_RetInt_ArgInt_Async.Execute));
            var injectedMethod = typeof(A_RetInt_ArgInt_Async).GetMethod(nameof(A_RetInt_ArgInt_Async.ExecuteWithStateChange));

            var a        = new A_RetInt_ArgInt_Async();
            var oldState = await a.Execute(state);

            //Act

            MethodReplacer.Replace(targetMethod, injectedMethod);
            var newState = await a.Execute(state);

            //Assert

            Assert.AreEqual(oldState, 0);
            Assert.AreEqual(newState, state);
        }
        public static MutatorsConfigurator <TRoot, TChild, TValue> MustBelongTo <TRoot, TChild, TValue>(
            this MutatorsConfigurator <TRoot, TChild, TValue> configurator,
            IEnumerable <TValue> values,
            IEqualityComparer <TValue> comparer = null,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var        methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var        pathToValue    = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue);
            var        pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);
            Expression contains       = comparer == null
                                      ? Expression.Call(containsMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body)
                                      : Expression.Call(containsWithComparerMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body, Expression.Constant(comparer));

            var condition = Expression.Convert(Expression.Not(contains), typeof(bool?));
            var message   = Expression.MemberInit(Expression.New(typeof(ValueMustBelongToText)),
                                                  Expression.Bind(typeof(ValueMustBelongToText).GetMember("Value").Single(), pathToValue.Body),
                                                  Expression.Bind(typeof(ValueMustBelongToText).GetMember("Values").Single(), Expression.Constant(values.Cast <object>().ToArray())));

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), Expression.Lambda <Func <TRoot, MultiLanguageTextBase> >(message, pathToChild.Parameters), type));
            return(configurator);
        }
        public static void BatchSet <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue>(
            this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator,
            Expression <Func <TDestValue, TSourceChild, Batch> > batch)
        {
            var        methodReplacer    = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var        pathToSourceChild = (Expression <Func <TSourceRoot, TSourceChild> >)methodReplacer.Visit(configurator.PathToSourceChild);
            var        pathToChild       = (Expression <Func <TDestRoot, TDestChild> >)methodReplacer.Visit(configurator.PathToChild);
            var        merger            = new ExpressionMerger(pathToSourceChild);
            var        initializers      = ((ListInitExpression)batch.Body).Initializers;
            Expression primaryKeyIsEmpty = null;

            foreach (var initializer in initializers)
            {
                Expression dest        = initializer.Arguments[0];
                var        clearedDest = ClearNotNull(dest);
                if (clearedDest != null)
                {
                    var current = Expression.Equal(clearedDest, Expression.Constant(null, clearedDest.Type));
                    primaryKeyIsEmpty = primaryKeyIsEmpty == null ? current : Expression.AndAlso(primaryKeyIsEmpty, current);
                }

                dest = clearedDest ?? dest;
                if (dest.Type != typeof(object))
                {
                    dest = Expression.Convert(dest, typeof(object));
                }
                Expression source = methodReplacer.Visit(initializer.Arguments[1]);
//                if(source.Type != typeof(object))
//                    source = Expression.Convert(source, typeof(object));
                LambdaExpression value = merger.Merge(Expression.Lambda(source, batch.Parameters[1]));
                if (dest.NodeType == ExpressionType.Convert)
                {
                    dest = ((UnaryExpression)dest).Operand;
                }
                dest = pathToChild.Merge(Expression.Lambda(dest, batch.Parameters[0])).Body;
                configurator.ToRoot().SetMutator(dest, EqualsToConfiguration.Create(typeof(TDestRoot), value, null));
                //configurator.Target(Expression.Lambda<Func<TDestValue, object>>(dest, batch.Parameters[0])).SetMutator(EqualsToConfiguration.Create(typeof(TDestRoot), value, null));
            }

            if (primaryKeyIsEmpty == null)
            {
                return;
            }
            var condition = (Expression <Func <TDestRoot, bool?> >)pathToChild.Merge(Expression.Lambda(Expression.Convert(methodReplacer.Visit(primaryKeyIsEmpty), typeof(bool?)), batch.Parameters[0]));

            foreach (var initializer in initializers)
            {
                Expression dest = initializer.Arguments[0];
                if (ClearNotNull(dest) != null)
                {
                    continue;
                }
                if (dest.Type != typeof(object))
                {
                    dest = Expression.Convert(dest, typeof(object));
                }
                if (dest.NodeType == ExpressionType.Convert)
                {
                    dest = ((UnaryExpression)dest).Operand;
                }
                dest = pathToChild.Merge(Expression.Lambda(dest, batch.Parameters[0])).Body;
                configurator.ToRoot().SetMutator(dest, NullifyIfConfiguration.Create(condition));

                //configurator.Target(Expression.Lambda<Func<TDestValue, object>>(dest, batch.Parameters[0])).SetMutator(NullifyIfConfiguration.Create(condition));
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        ///     Разворачиваем всякие ичи-хуичи в нормальные циклы посредством хитровыебнутой функции MutatorsHelperFunctions.ForEach
        /// </summary>
        private static void BuildTreeMutatorForArray(this ModelConfigurationNode node, ModelConfigurationNode child, Stack <ModelConfigurationEdge> edges, ModelConfigurationNode root, List <KeyValuePair <Expression, Expression> > aliases, List <Expression> localResult, HashSet <ModelConfigurationNode> visitedNodes, HashSet <ModelConfigurationNode> processedNodes, Expression path, List <Expression> globalResult, List <ParameterExpression> invariantParameters)
        {
            // We want to transform this:
            //   Target(target => target.A.B.Each().S).Set(source => source.T.R.Current().U.S)
            // To the following code:
            //   var array = source.T.R.ToArray();
            //   if(target.A.B == null || target.A.B.Length != source.T.R.Length)
            //   {
            //       if(target.A.B == null)
            //       {
            //           target.A.B = new object[source.T.R.Length];
            //       }
            //       else
            //       {
            //           var tmp = target.A.B;
            //           Array.Resize(ref tmp, source.T.R.Length);
            //           target.A.B = tmp;
            //       }
            //   }
            //   MutatorsHelperFunctions.ForEach(target.A.B, (b, i) =>
            //       {
            //           b.S = array[i].U.S;
            //           return b;
            //       });

            // Create parameters for lambda to use in ForEach method and create aliases for Each() and CurrentIndex()
            var childParameter = Expression.Parameter(child.NodeType, child.NodeType.Name);
            var indexParameter = Expression.Parameter(typeof(int));
            var item           = node.Path.MakeEachCall(child.NodeType);
            var index          = item.MakeCurrentIndexCall(child.NodeType);

            aliases.Add(new KeyValuePair <Expression, Expression>(childParameter, item));
            aliases.Add(new KeyValuePair <Expression, Expression>(indexParameter, index));

            // Find a source array to take values from
            // todo ich: почему только первый?
            var arrays            = node.GetArrays();
            var canonizedFullPath = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod).Visit(node.Path);
            var array             = arrays.FirstOrDefault(pair => !new ExpressionWrapper(pair.Value, false).Equals(new ExpressionWrapper(canonizedFullPath, false))).Value;

            ParameterExpression arrayParameter = null;
            var itemType = array == null ? null : array.Type.GetItemType();

            if (array != null)
            {
                // If any array found - create a variable for it and aliases for Each() and CurrentIndex()
                arrayParameter = Expression.Variable(itemType.MakeArrayType());
                invariantParameters.Add(array.ExtractParameters().Single());
                invariantParameters.Add(arrayParameter);
                invariantParameters.Add(indexParameter);
                var arrayEach         = array.MakeEachCall(itemType);
                var arrayCurrentIndex = arrayEach.MakeCurrentIndexCall(itemType);
                aliases.Add(new KeyValuePair <Expression, Expression>(Expression.ArrayIndex(arrayParameter, indexParameter), arrayEach));
                aliases.Add(new KeyValuePair <Expression, Expression>(indexParameter, arrayCurrentIndex));
                array = array.ResolveAliases(aliases).EliminateLinq();
            }

            // Build mutators in subtree into a separate list, to put them inside ForEach lambda
            var childResult = new List <Expression>();

            child.BuildTreeMutator(edges, root, aliases, childResult, visitedNodes, processedNodes, globalResult, invariantParameters);

            // Remove all created aliases
            aliases.RemoveAt(aliases.Count - 1);
            aliases.RemoveAt(aliases.Count - 1);
            if (array != null)
            {
                invariantParameters.RemoveAt(invariantParameters.Count - 1);
                aliases.RemoveAt(aliases.Count - 1);
                aliases.RemoveAt(aliases.Count - 1);
            }

            if (childResult.Count > 0)
            {
                // ForEach method requires mutators block to return the target item
                childResult.Add(childParameter);

                // Optimization of block size to avoid big functions
                var action = Expression.Block(childResult.SplitToBatches());
                // Make a call to MutatorsHelperFunctions.ForEach
                var        forEach = action.ExtractLoopInvariantFatExpressions(invariantParameters, exp => Expression.Call(null, forEachMethod.MakeGenericMethod(child.NodeType), new[] { path, Expression.Lambda(exp, childParameter, indexParameter) }));
                Expression result;
                if (array == null)
                {
                    result = forEach;
                }
                else
                {
                    // If we had found an array
                    // Assign it to the array variable with a ToArray() call.
                    Expression assign = Expression.Assign(arrayParameter, Expression.Call(toArrayMethod.MakeGenericMethod(itemType), new[] { array }));
                    // Add a check if target array is null or needs to be resized
                    var resizeIfNeeded = CreateOrResizeArrayIfNeeded(child, path, arrayParameter);
                    result = Expression.Block(new[] { arrayParameter }, assign, resizeIfNeeded, forEach);
                }

                localResult.Add(result);
            }

            if (array != null)
            {
                invariantParameters.RemoveAt(invariantParameters.Count - 1);
                invariantParameters.RemoveAt(invariantParameters.Count - 1);
            }
        }