private static Expression HandleNullableValueTypes(ProposedMemberMapping member, Expression accessMember) { if (member.DestinationMember.PropertyOrFieldType.IsNullableValueType() && !member.SourceMember.PropertyOrFieldType.IsNullableValueType()) { var nullableType = member .DestinationMember .PropertyOrFieldType .GetGenericArguments() .Single(); accessMember = Expression.New(member.DestinationMember.PropertyOrFieldType.GetConstructor(new[] { nullableType }), accessMember); } else if (!member.DestinationMember.PropertyOrFieldType.IsNullableValueType() && member.SourceMember.PropertyOrFieldType.IsNullableValueType()) { var nullableType = member.SourceMember.PropertyOrFieldType.GetGenericArguments().Single(); accessMember = Expression.Condition(Expression.Property(accessMember, "HasValue"), Expression.Property(accessMember, "Value"), Expression.Default(member.DestinationMember.PropertyOrFieldType)); } return(accessMember); }
private static Expression HandleNullableValueTypes(ProposedMemberMapping member, Expression accessMember) { if (member.DestinationMember.PropertyOrFieldType.IsNullableValueType() && !member.SourceMember.PropertyOrFieldType.IsNullableValueType()) { var nullableType = member .DestinationMember .PropertyOrFieldType .GetGenericArguments() .Single(); accessMember = Expression.New(member.DestinationMember.PropertyOrFieldType.GetConstructor(new[] { nullableType }), accessMember); } else if (!member.DestinationMember.PropertyOrFieldType.IsNullableValueType() && member.SourceMember.PropertyOrFieldType.IsNullableValueType()) { var nullableType = member.SourceMember.PropertyOrFieldType.GetGenericArguments().Single(); accessMember = Expression.Condition(Expression.Property(accessMember, "HasValue"), Expression.Property(accessMember, "Value"), Expression.Default(member.DestinationMember.PropertyOrFieldType)); } return accessMember; }
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); }
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); }
public bool Equals(ProposedMemberMapping mapping) { return(this.DestinationMember == mapping.DestinationMember && this.SourceMember == mapping.SourceMember); }
/// <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); } } }
/// <summary> /// Assigns an expression that can be pretty much anything to a destination mapping. /// </summary> /// <returns></returns> private BinaryExpression AssignSimpleProperty( ProposedMemberMapping member, MemberExpression destination, Expression source, ProposedTypeMapping typeMapping, bool usesConversionFunction ) { // If the destination is nullable but the source expression returns a non-nullable value type. if (destination.Type.IsNullableValueType() && !source.Type.IsNullableValueType()) { source = HandleDestinationNullableValueType(destination, source); } // If the destination is not a nullable value type but the source expression does return one. else if (!destination.Type.IsNullableValueType() && source.Type.IsNullableValueType()) { source = HandleSourceNullableValueType(destination, source); } // dest.Member = source.Member != null ? source.Member : dest.Member else if (source.Type.IsClass && options.Conventions.MakeCloneIfDestinationIsTheSameAsSource && source.Type.IsAssignableFrom(destination.Type) && !typeMapping.NewInstanceCreated && !usesConversionFunction) { source = Expression.Condition(Expression.NotEqual(source, Expression.Constant(null)), source, destination); } else if (destination.Type.IsNullableValueType() && source.Type.IsNullableValueType()) { source = HandleNullableValueTypes(destination, source); } if (!source.Type.IsAssignableFrom(destination.Type)) { // cast source = Expression.Convert(source, destination.Type); } return Expression.Assign(destination, source); }
public bool Equals(ProposedMemberMapping mapping) { return this.DestinationMember == mapping.DestinationMember && this.SourceMember == mapping.SourceMember; }
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); }