private static MemberInitExpression createMemberInit(ParameterExpression parameterExpression, Type destination, Type source = null, Type filter = null, ObjectChangesRegister changesRegister = null)
        {
            var internalBindings = BuildBindings(destination, source, filter);
            IEnumerable <MemberAssignment> bindings;

            if (changesRegister != null)
            {
                changesRegister.MoveToComplex();
                var lbindings = new List <MemberAssignment>();
                if (internalBindings != null)
                {
                    foreach (var binding in internalBindings)
                    {
                        var bind = BuildBinding(parameterExpression, binding, null, true);
                        lbindings.Add(bind);
                        changesRegister
                        .AddChange(new ObjectChangesRegister(binding.Destination as PropertyInfo, false, null, bind.Expression));
                    }
                }
                bindings = lbindings;
            }
            else
            {
                bindings = internalBindings
                           .Select(m => BuildBinding(parameterExpression, m, null, changesRegister != null));
            }

            return(Expression.MemberInit(Expression.New(destination), bindings));
        }
        private static MemberInitExpression completeMemberInit(
            MemberInitExpression node,
            ParameterExpression parameterExpression,
            Type filter   = null,
            string prefix = null,
            Stack <PropertyInfo> sourceProperties = null,
            ObjectChangesRegister changesRegister = null)
        {
            var customAssignements  = node.Bindings.Where(m => m.BindingType == MemberBindingType.Assignment).Select(m => m as MemberAssignment).ToList();
            var assignedProperties  = customAssignements.Select(m => m.Member.Name).ToList();
            var internalProjections = customAssignements.Where(m => getNestedSelect(m.Expression) != null);
            var otherAssignements   = customAssignements.Except(internalProjections);
            List <MemberAssignment> modifiedAssignements    = null;
            List <MemberAssignment> modifiedAssignementsOld = null;

            if (internalProjections != null)
            {
                foreach (var projection in internalProjections)
                {
                    var select             = getNestedSelect(projection.Expression);
                    var exp                = select.Arguments[1] as LambdaExpression;
                    var originalCollection = select.Arguments[0] as MemberExpression;
                    if (exp != null)
                    {
                        Type     childFilter  = null;
                        var      propertyInfo = (projection.Member as PropertyInfo);
                        TypeInfo childType    = propertyInfo.PropertyType.GetTypeInfo();
                        if (childType.IsGenericType && childType.GenericTypeArguments.Length == 1 && childType.GenericTypeArguments[0].GetTypeInfo().IsInterface)
                        {
                            childFilter = childType.GenericTypeArguments[0];
                        }
                        var childChangesRegister = changesRegister == null ? null:  new ObjectChangesRegister(propertyInfo, true, childType.GenericTypeArguments[0], null, originalCollection.Member as PropertyInfo);
                        var newExpression        = copyCallChain(projection.Expression as MethodCallExpression, select,
                                                                 Expression.TypeAs(
                                                                     Expression.Call(select.Method, originalCollection, BuildInternalExpression(exp, childFilter, childChangesRegister)),
                                                                     select.Method.ReturnType)
                                                                 );
                        var newAssignement = changesRegister == null?Expression.Bind(projection.Member,
                                                                                     newExpression)
                                                 :
                                                 Expression.Bind(projection.Member,
                                                                 Expression.Condition(Expression.Equal(copyMemberAccesses(select.Arguments[0]), Expression.Constant(null)),
                                                                                      Expression.Constant(null, newExpression.Type),
                                                                                      newExpression));

                        if (changesRegister != null)
                        {
                            childChangesRegister.SetExpression(newExpression);
                            changesRegister.AddChange(childChangesRegister);
                        }

                        if (modifiedAssignements == null)
                        {
                            modifiedAssignements    = new List <MemberAssignment>();
                            modifiedAssignementsOld = new List <MemberAssignment>();
                        }
                        modifiedAssignements.Add(newAssignement);
                        modifiedAssignementsOld.Add(projection);
                    }
                }
            }
            if (otherAssignements != null)
            {
                foreach (var assignement in otherAssignements)
                {
                    var newChange = changesRegister == null ? null : new ObjectChangesRegister(assignement.Member as PropertyInfo, false, null, null);
                    var newNode   = processTreeRec(assignement.Expression, parameterExpression, filter, prefix, sourceProperties, assignement.Member as PropertyInfo, newChange);
                    if (changesRegister != null)
                    {
                        newChange.SetExpression(newNode);
                        changesRegister.AddChange(newChange);
                    }
                    if (newNode != assignement.Expression)
                    {
                        var newAssignement = Expression.Bind(assignement.Member, newNode);
                        if (modifiedAssignements == null)
                        {
                            modifiedAssignements    = new List <MemberAssignment>();
                            modifiedAssignementsOld = new List <MemberAssignment>();
                        }
                        modifiedAssignements.Add(newAssignement);
                        modifiedAssignementsOld.Add(assignement);
                    }
                }
            }
            var innerBindings = BuildBindings(node.NewExpression.Type,
                                              sourceProperties != null && sourceProperties.Count > 0 ?
                                              sourceProperties.Peek().PropertyType :
                                              parameterExpression.Type,
                                              filter, prefix)
                                .Where(m => !assignedProperties.Contains(m.Destination.Name));
            IEnumerable <MemberAssignment> bindings;

            if (innerBindings != null && changesRegister != null)
            {
                var lbindings = new List <MemberAssignment>();
                foreach (var binding in innerBindings)
                {
                    var bind = BuildBinding(parameterExpression, binding, sourceProperties, true);
                    lbindings.Add(bind);
                    changesRegister
                    .AddChange(new ObjectChangesRegister(binding.Destination as PropertyInfo, false, null, bind.Expression));
                }
                bindings = lbindings.Union(customAssignements);
            }
            else
            {
                bindings = innerBindings
                           .Select(m => BuildBinding(parameterExpression, m, sourceProperties, changesRegister != null))
                           .Union(customAssignements);
            }
            if (modifiedAssignements != null && modifiedAssignements.Count > 0)
            {
                bindings = bindings.Except(modifiedAssignementsOld)
                           .Union(modifiedAssignements);
            }
            return(Expression.MemberInit(node.NewExpression, bindings));
        }