protected override Expression VisitMember(MemberExpression node)
        {
            string sourcePath;

            var parameterExpression = node.GetParameterExpression();

            if (parameterExpression == null)
            {
                return(base.VisitMember(node));
            }

            InfoDictionary.Add(parameterExpression, TypeMappings);
            var sType = parameterExpression.Type;

            if (sType != null && InfoDictionary.ContainsKey(parameterExpression) && node.IsMemberExpression())
            {
                sourcePath = node.GetPropertyFullName();
            }
            else
            {
                return(base.VisitMember(node));
            }

            var propertyMapInfoList = new List <PropertyMapInfo>();

            FindDestinationFullName(sType, InfoDictionary[parameterExpression].DestType, sourcePath, propertyMapInfoList);
            string fullName;

            if (propertyMapInfoList.Any(x => x.CustomExpression != null))//CustomExpression takes precedence over DestinationPropertyInfo
            {
                var last = propertyMapInfoList.Last(x => x.CustomExpression != null);
                var beforeCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) =>
                {
                    if (propertyMapInfoList.IndexOf(next) < propertyMapInfoList.IndexOf(last))
                    {
                        list.Add(next);
                    }
                    return(list);
                });

                var afterCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) =>
                {
                    if (propertyMapInfoList.IndexOf(next) > propertyMapInfoList.IndexOf(last))
                    {
                        list.Add(next);
                    }
                    return(list);
                });


                fullName = BuildFullName(beforeCustExpression);

                var visitor = new PrependParentNameVisitor(last.CustomExpression.Parameters[0].Type /*Parent type of current property*/, fullName, InfoDictionary[parameterExpression].NewParameter);

                var ex = propertyMapInfoList[propertyMapInfoList.Count - 1] != last
                    ? visitor.Visit(last.CustomExpression.Body.MemberAccesses(afterCustExpression))
                    : visitor.Visit(last.CustomExpression.Body);

                var v = new FindMemberExpressionsVisitor(InfoDictionary[parameterExpression].NewParameter);
                v.Visit(ex);

                return(v.Result);
            }
            fullName = BuildFullName(propertyMapInfoList);
            var me = ExpressionHelpers.MemberAccesses(fullName, InfoDictionary[parameterExpression].NewParameter);

            if (me.Expression.NodeType == ExpressionType.MemberAccess && (me.Type == typeof(string) || me.Type.GetTypeInfo().IsValueType || (me.Type.GetTypeInfo().IsGenericType &&
                                                                                                                                             me.Type.GetGenericTypeDefinition() == typeof(Nullable <>) &&
                                                                                                                                             Nullable.GetUnderlyingType(me.Type).GetTypeInfo().IsValueType)))
            {
                return(me.Expression);
            }

            return(me);
        }
        protected override Expression VisitMember(MemberExpression node)
        {
            string sourcePath;

            var parameterExpression = node.GetParameterExpression();

            if (parameterExpression == null)
            {
                return(base.VisitMember(node));
            }

            InfoDictionary.Add(parameterExpression, TypeMappings);

            var sType = parameterExpression.Type;

            if (InfoDictionary.ContainsKey(parameterExpression) && node.IsMemberExpression())
            {
                sourcePath = node.GetPropertyFullName();
            }
            else
            {
                return(base.VisitMember(node));
            }

            var propertyMapInfoList = new List <PropertyMapInfo>();

            FindDestinationFullName(sType, InfoDictionary[parameterExpression].DestType, sourcePath, propertyMapInfoList);
            string fullName;

            if (propertyMapInfoList.Any(x => x.CustomExpression != null))
            {
                var last = propertyMapInfoList.Last(x => x.CustomExpression != null);
                var beforeCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) =>
                {
                    if (propertyMapInfoList.IndexOf(next) < propertyMapInfoList.IndexOf(last))
                    {
                        list.Add(next);
                    }
                    return(list);
                });

                var afterCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) =>
                {
                    if (propertyMapInfoList.IndexOf(next) > propertyMapInfoList.IndexOf(last))
                    {
                        list.Add(next);
                    }
                    return(list);
                });

                fullName = BuildFullName(beforeCustExpression);
                var visitor = new PrependParentNameVisitor(last.CustomExpression.Parameters[0].Type /*Parent type of current property*/, fullName, InfoDictionary[parameterExpression].NewParameter);

                var ex = propertyMapInfoList[propertyMapInfoList.Count - 1] != last
                    ? visitor.Visit(last.CustomExpression.Body.MemberAccesses(afterCustExpression))
                    : visitor.Visit(last.CustomExpression.Body);

                this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, ex.Type);
                return(ex);
            }
            fullName = BuildFullName(propertyMapInfoList);
            var me = ExpressionHelpers.MemberAccesses(fullName, InfoDictionary[parameterExpression].NewParameter);

            this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, me.Type);
            return(me);
        }