Exemple #1
0
        public void CombineWithOtherCustomMappings(CustomMapping root, IEnumerable <CustomMapping> mappings)
        {
            lock (root)
            {
                foreach (var otherMapping in mappings)
                {
                    foreach (var m in otherMapping.Members)
                    {
                        if (!root.Members.Contains(m))
                        {
                            var oldParams = otherMapping.ArgumentParameters.Select(p => p.Parameter).ToList();
                            var newParams = root.ArgumentParameters.Select(p => p.Parameter).ToList();

                            oldParams.Add(otherMapping.SourceParameter);
                            newParams.Add(root.SourceParameter);

                            var visitor = new ParameterVisitor(oldParams, newParams);

                            var member = new MemberExpressionTuple
                            {
                                Expression = visitor.Visit(m.Expression),
                                Member     = m.Member
                            };

                            root.Members.Add(member);
                        }
                    }
                }
            }
        }
Exemple #2
0
        private static CustomMapping GetCustomMappingFromNewExpression(Type destinationType, NewExpression expression)
        {
            var newMapping = new CustomMapping();

            newMapping.DestinationType = destinationType;

            for (var i = 0; i < expression.Arguments.Count; i++)
            {
                var member   = expression.Members[i];
                var argument = expression.Arguments[i];

                var memberOnDestination = destinationType.GetMember(member.Name).FirstOrDefault();

                if (memberOnDestination == null)
                {
                    throw new ArgumentException(string.Format("Member {0} does not exist on type {1}", member.Name, destinationType.Name));
                }

                var memberExpression = new MemberExpressionTuple();

                memberExpression.Member = memberOnDestination;

                if (argument is NewExpression)
                {
                    var cm = GetCustomMappingFromNewExpression(memberExpression.Member.PropertyOrFieldType, (NewExpression)argument);

                    if (cm != null)
                    {
                        newMapping.CustomMappings.Add(cm);
                    }
                }
                else
                {
                    memberExpression.Expression = argument;
                }

                newMapping.Members.Add(memberExpression);
            }
            return(newMapping);
        }
Exemple #3
0
        private static CustomMapping GetCustomMappingFromMemberInitExpression(Type destinationType, MemberInitExpression expression)
        {
            var newMapping = new CustomMapping();

            newMapping.DestinationType = destinationType;

            foreach (MemberAssignment assignment in expression.Bindings)
            {
                var member   = assignment.Member;
                var argument = assignment.Expression;

                var memberOnDestination = destinationType.GetMember(member.Name).FirstOrDefault();

                if (memberOnDestination == null)
                {
                    throw new ArgumentException(string.Format("Member {0} does not exist on type {1}", member.Name, destinationType.Name));
                }

                var memberExpression = new MemberExpressionTuple();

                memberExpression.Member = memberOnDestination;

                var argAsNewExpression = argument as NewExpression;

                if (argAsNewExpression != null && argAsNewExpression.Members != null)
                {
                    newMapping.CustomMappings.Add(GetCustomMappingFromNewExpression(memberExpression.Member.PropertyOrFieldType, (NewExpression)argument));
                }
                else
                {
                    memberExpression.Expression = argument;
                }

                newMapping.Members.Add(memberExpression);
            }

            return(newMapping);
        }
        private void BuildMemberAssignmentExpressions(Expression sourceAccess, List<MemberBinding> memberBindings, ProposedMemberMapping member, CustomMapping customMapping)
        {
            if (member.Ignored)
              {
            return;
              }

              Expression customExpression;

              MemberAssignment bindSourceToDest;

              if (customMapping != null && (customExpression = customMapping.GetExpressionForMember(member.DestinationMember)) != null)
              {
            processor.ParametersToReplace.Add(new ProjectionExpressionTuple(customMapping.SourceParameter, sourceAccess));

            bindSourceToDest = Expression.Bind(member.DestinationMember, customExpression);
              }
              else
              {
            Expression accessMember = Expression.MakeMemberAccess(sourceAccess, member.SourceMember);

            accessMember = HandleNullableValueTypes(member, accessMember);

            bindSourceToDest = Expression.Bind(member.DestinationMember, accessMember);
              }

              memberBindings.Add(bindSourceToDest);
        }
        /// <summary>
        /// Processes a mapping for a type.
        /// </summary>
        private void BuildTypeMappingExpressions(
      ParameterExpression source,
      ParameterExpression destination,
      ProposedTypeMapping typeMapping,
      List<Expression> expressions,
      CustomMapping customMapping = null
    )
        {
            // If there's custom mapping defined
              if (customMapping != null)
              {
            // Custom mapping has a source parameter that needs to be replaced with actual parameter
            mapProcessor.ParametersToReplace.Add(new ExpressionTuple(customMapping.SourceParameter, source));

            // Custom mapping may contain more parameters that represent arguments in the custom mapping
            foreach (var param in customMapping.ArgumentParameters)
            {
              // Find the corresponding parameter that we want to replace the custom mapping's placeholder with
              var correspondingParam = this.Parameters.Single(p => p.Index == param.Index);
              mapProcessor.ParametersToReplace.Add(new ExpressionTuple(param.Parameter, correspondingParam.Parameter));
            }
              }

              // Simple property assignments
              foreach (var member in typeMapping.ProposedMappings)
              {
            BuildMemberAssignmentExpressions(source, destination, member, expressions, typeMapping, customMapping);
              }

              // Nested type mappings
              foreach (var complexTypeMapping in typeMapping.ProposedTypeMappings)
              {
            // If it's a collection type
            if (typeMapping.IsEnumerable || CollectionTypeHelper.IsEnumerable(complexTypeMapping))
            {
              BuildEnumerableMappingExpressions(source, destination, complexTypeMapping, expressions);
            }
            else
            {
              // If it's not a collection but just a nested type
              BuildComplexTypeMappingExpressions(source, destination, complexTypeMapping, expressions);
            }
              }
        }
        /// <summary>
        /// Assign source member to a destination mapping, applying any custom mappings in the process.
        /// </summary>
        private void BuildMemberAssignmentExpressions(
      ParameterExpression source,
      ParameterExpression destination,
      ProposedMemberMapping member,
      List<Expression> expressions,
      ProposedTypeMapping typeMapping,
      CustomMapping customMapping = null
    )
        {
            if (member.Ignored)
              {
            return;
              }

              Expression condition = null;

              if (member.Condition != null)
              {
            mapProcessor.ParametersToReplace.Add(new ExpressionTuple(member.Condition.Parameters.Single(), this.sourceParameter));

            condition = member.Condition.Body;
              }

              var destMember = Expression.MakeMemberAccess(destination, member.DestinationMember);

              Expression assignSourceToDest = null;

              Expression customExpression = null;

              Expression assignConversionToDest = null;

              LambdaExpression conversionFunction = null;

              bool conversionReturnTypeSameAsParameterType = false;

              ParameterExpression conversionParameter = null;

              if (customMapping != null)
              {
            conversionFunction = customMapping.GetConversionFunction(member.SourceMember, member.DestinationMember);

            if (conversionFunction != null)
            {
              conversionParameter = conversionFunction.Parameters.Single();

              conversionReturnTypeSameAsParameterType = conversionParameter.Type == conversionFunction.ReturnType;
            }
              }

              if (customMapping != null && (customExpression = customMapping.GetExpressionForMember(member.DestinationMember)) != null)
              {
            assignSourceToDest = Expression.Assign(destMember, customExpression);
              }
              else if (member.HierarchicalMapping != null)
              {
            var accessHierarchy = BuildHierarchicalExpression(source, member.HierarchicalMapping, null);

            if (destMember.Type.IsNullableValueType())
            {
              accessHierarchy = Expression.Convert(accessHierarchy, destMember.Type);
            }

            assignSourceToDest = Expression.Assign(destMember, accessHierarchy);
              }
              else
              {
            Expression sourceExpression = Expression.MakeMemberAccess(source, member.SourceMember);

            bool usesConversionFunction = false;

            if (conversionFunction != null && !conversionReturnTypeSameAsParameterType)
            {
              ValidateConversionFunction(conversionFunction, conversionParameter, sourceExpression, destMember);

              this.mapProcessor.ParametersToReplace.Add(new ExpressionTuple(conversionParameter, sourceExpression));

              sourceExpression = conversionFunction.Body;
              usesConversionFunction = true;
            }

            assignSourceToDest = AssignSimpleProperty(member, destMember, sourceExpression, typeMapping, usesConversionFunction);
              }

              if (conversionFunction != null && conversionReturnTypeSameAsParameterType)
              {
            this.mapProcessor.ParametersToReplace.Add(new ExpressionTuple(conversionParameter, destMember));

            assignConversionToDest = Expression.Assign(destMember, conversionFunction.Body);
              }

              // If a condition to the mapping was specified
              if (condition != null)
              {
            if (assignConversionToDest != null)
            {
              assignSourceToDest = Expression.Block(assignSourceToDest, assignConversionToDest);
            }

            var ifCondition = Expression.IfThen(condition, assignSourceToDest);
            expressions.Add(ifCondition);
              }
              else
              {
            expressions.Add(assignSourceToDest);
            if (assignConversionToDest != null)
            {
              expressions.Add(assignConversionToDest);
            }
              }
        }
        private void BuildTypeMappingExpressions(ParameterExpression source, ParameterExpression destination, ProposedTypeMapping typeMapping, List<Expression> expressions, List<ParameterExpression> newParams, CustomMapping customMapping = null)
        {
            foreach (var member in typeMapping.ProposedMappings)
              {
            BuildSimpleTypeMappingExpressions(source, destination, member, expressions, newParams, customMapping);
              }

              foreach (var complexTypeMapping in typeMapping.ProposedTypeMappings)
              {
            if (typeMapping.IsEnumerable || CollectionTypeHelper.IsEnumerable(complexTypeMapping))
            {
              BuildCollectionComplexTypeMappingExpressions(source, destination, complexTypeMapping, expressions, newParams);
            }
            else
            {
              BuildNonCollectionComplexTypeMappingExpressions(source, destination, complexTypeMapping, expressions, newParams);
            }
              }
        }
        private void BuildSimpleTypeMappingExpressions(ParameterExpression source, ParameterExpression destination, ProposedMemberMapping member, List<Expression> expressions, List<ParameterExpression> newParams, CustomMapping customMapping = null)
        {
            Expression sourceExpression = Expression.PropertyOrField(source, member.SourceMember.Name);
              var destMember = Expression.PropertyOrField(destination, member.DestinationMember.Name);

              BinaryExpression assignSourceToDest;

              Expression customExpression;

              if (customMapping != null && (customExpression = customMapping.GetExpressionForMember(member.DestinationMember)) != null)
              {
            var visitor = new ParameterVisitor(customMapping.Parameter, source);

            customExpression = visitor.Visit(customExpression);

            assignSourceToDest = Expression.Assign(destMember, customExpression);

              }
              else
              {
            assignSourceToDest = Expression.Assign(destMember, sourceExpression);
              }

              expressions.Add(assignSourceToDest);
        }
        private static CustomMapping GetCustomMappingFromNewExpression(Type destinationType, NewExpression expression)
        {
            var newMapping = new CustomMapping();

              newMapping.DestinationType = destinationType;

              for (var i = 0; i < expression.Arguments.Count; i++)
              {
            var member = expression.Members[i];
            var argument = expression.Arguments[i];

            var memberOnDestination = destinationType.GetMember(member.Name).FirstOrDefault();

            if (memberOnDestination == null)
            {
              throw new ArgumentException(string.Format("Member {0} does not exist on type {1}", member.Name, destinationType.Name));
            }

            var memberExpression = new MemberExpressionTuple();

            memberExpression.Member = memberOnDestination;

            if (argument is NewExpression)
            {
              newMapping.CustomMappings.Add(GetCustomMappingFromNewExpression(memberExpression.Member.PropertyOrFieldType, (NewExpression)argument));
            }
            else
            {
              memberExpression.Expression = argument;
            }

            newMapping.Members.Add(memberExpression);

              }
              return newMapping;
        }