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 Expression processTreeRec(
            Expression node,
            ParameterExpression parameterExpression,
            Type filter   = null,
            string prefix = null,
            Stack <PropertyInfo> sourceProperties = null,
            PropertyInfo currProperty             = null,
            ObjectChangesRegister changesRegister = null)
        {
            if (node.NodeType == ExpressionType.MemberInit)
            {
                if (changesRegister != null)
                {
                    changesRegister.MoveToComplex();
                }
                var currType = sourceProperties != null &&
                               sourceProperties.Count > 0 ? sourceProperties.Peek().PropertyType : parameterExpression.Type;
                string newPrefix      = prefix == null ? currProperty?.Name : prefix + currProperty?.Name;;
                var    sourceProperty = newPrefix == null ? null : currType.GetProperty(newPrefix);
                if (currProperty != null && currProperty.PropertyType.GetTypeInfo().IsInterface)
                {
                    filter = currProperty.PropertyType;
                }
                else
                {
                    filter = null;
                }
                if (sourceProperty != null)
                {
                    if (sourceProperties == null)
                    {
                        sourceProperties = new Stack <PropertyInfo>();
                    }
                    sourceProperties.Push(sourceProperty);
                    var res = completeMemberInit(node as MemberInitExpression, parameterExpression, filter, null, sourceProperties, changesRegister);
                    sourceProperties.Pop();
                    if (sourceProperties.Count == 0)
                    {
                        sourceProperties = null;
                    }
                    return(res);
                }
                else
                {
                    return(completeMemberInit(node as MemberInitExpression, parameterExpression, filter, newPrefix, sourceProperties, changesRegister));
                }
            }

            else if (node.NodeType == ExpressionType.Conditional)
            {
                var cond    = node as ConditionalExpression;
                var ifTrue  = processTreeRec(cond.IfTrue, parameterExpression, filter, prefix, sourceProperties, currProperty, changesRegister);
                var ifFalse = processTreeRec(cond.IfFalse, parameterExpression, filter, prefix, sourceProperties, currProperty, changesRegister);
                if (ifTrue == cond.IfTrue && ifFalse == cond.IfFalse)
                {
                    return(node);
                }
                return(Expression.Condition(cond.Test,
                                            ifTrue,
                                            ifFalse));
            }
            else if (node.NodeType == ExpressionType.Convert)
            {
                var conv      = node as UnaryExpression;
                var toConvert = processTreeRec(conv.Operand, parameterExpression, filter, prefix, sourceProperties, currProperty, changesRegister);
                if (toConvert == conv.Operand)
                {
                    return(node);
                }
                return(Expression.Convert(toConvert,
                                          conv.Type, conv.Method));
            }
            else if (node.NodeType == ExpressionType.ConvertChecked)
            {
                var conv      = node as UnaryExpression;
                var toConvert = processTreeRec(conv.Operand, parameterExpression, filter, prefix, sourceProperties, currProperty, changesRegister);
                if (toConvert == conv.Operand)
                {
                    return(node);
                }
                return(Expression.ConvertChecked(toConvert,
                                                 conv.Type, conv.Method));
            }
            else if (node.NodeType == ExpressionType.New)
            {
                if (changesRegister != null)
                {
                    changesRegister.MoveToComplex();
                }
                return(node);
            }
            else
            {
                return(node);
            }
        }